@titan-design/authority 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +972 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
- package/src/table.json +867 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Henry Jewkes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# @titan-design/authority
|
|
2
|
+
|
|
3
|
+
The owner-approved authority decision table as data, with its zod schema and a pure
|
|
4
|
+
evaluator. For every action class (merge, release, secret read, spawn, hardware actuation
|
|
5
|
+
and more) and every actor class (owner at a terminal, owner remote, coordinator, worker,
|
|
6
|
+
headless run, automation) the table names exactly one verdict: `allow`, `gate` or `deny`.
|
|
7
|
+
|
|
8
|
+
Tier 0 of the titan-platform DAG. No titan dependencies, no Node built-ins; `zod` is a peer
|
|
9
|
+
dependency.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { DEFAULT_TABLE, canResolve, evaluate } from "@titan-design/authority";
|
|
13
|
+
|
|
14
|
+
evaluate(DEFAULT_TABLE, { action: "merge", actor: { class: "worker", id: "w1" }, tainted: false, subject: {} });
|
|
15
|
+
// { verdict: "deny", ruleId: "MRG-WK", reason: "MRG-WK denies merge by worker" }
|
|
16
|
+
|
|
17
|
+
canResolve(DEFAULT_TABLE, "MRG-CO", { class: "coordinator", tainted: false }); // false
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- `evaluate(table, request)`: the decision for one request. No matching rule means deny.
|
|
21
|
+
A tainted actor on a rule marked `taintEscalates` gets a gate only the owner at a
|
|
22
|
+
terminal resolves.
|
|
23
|
+
- `canResolve(table, ruleId, resolver)`: false for any agent or automation class and for
|
|
24
|
+
any tainted resolver.
|
|
25
|
+
- `policyTableSchema`: rejects a table that misses or repeats an action by actor pair, or
|
|
26
|
+
names anyone but `owner-terminal` or `owner-remote` as a resolver.
|
|
27
|
+
- `DEFAULT_TABLE`: the approved table, also shipped as `@titan-design/authority/table.json`
|
|
28
|
+
for plain-node hooks.
|
|
29
|
+
|
|
30
|
+
The library enforces nothing by itself. See the reference page for the full table.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const ACTOR_CLASSES: readonly ["owner-terminal", "owner-remote", "coordinator", "worker", "headless", "automation"];
|
|
4
|
+
/** The only classes that may resolve a gate: the owner, at a terminal or through a verified remote channel. */
|
|
5
|
+
declare const RESOLVER_CLASSES: readonly ["owner-terminal", "owner-remote"];
|
|
6
|
+
declare const ACTION_CLASSES: readonly ["merge", "release", "secret-read", "untrusted-ingest", "private-to-public", "private-egress", "hardware-actuate", "hardware-stop", "destructive-remote", "destructive-local", "destructive-foreign", "spawn", "spend-over-cap", "authority-config", "human-verb"];
|
|
7
|
+
declare const VERDICTS: readonly ["allow", "gate", "deny"];
|
|
8
|
+
/** Codes for the record each rule expects to leave behind, from a decision record to a device read-back. */
|
|
9
|
+
declare const EVIDENCE_KINDS: readonly ["E-dec", "E-gate", "E-ref", "E-byp", "E-gh", "E-npm", "E-spn", "E-prin", "E-dev"];
|
|
10
|
+
type ActorClass = (typeof ACTOR_CLASSES)[number];
|
|
11
|
+
type ResolverClass = (typeof RESOLVER_CLASSES)[number];
|
|
12
|
+
type ActionClass = (typeof ACTION_CLASSES)[number];
|
|
13
|
+
type Verdict = (typeof VERDICTS)[number];
|
|
14
|
+
type EvidenceKind = (typeof EVIDENCE_KINDS)[number];
|
|
15
|
+
|
|
16
|
+
declare const ruleSchema: z.ZodObject<{
|
|
17
|
+
id: z.ZodString;
|
|
18
|
+
action: z.ZodEnum<{
|
|
19
|
+
merge: "merge";
|
|
20
|
+
release: "release";
|
|
21
|
+
"secret-read": "secret-read";
|
|
22
|
+
"untrusted-ingest": "untrusted-ingest";
|
|
23
|
+
"private-to-public": "private-to-public";
|
|
24
|
+
"private-egress": "private-egress";
|
|
25
|
+
"hardware-actuate": "hardware-actuate";
|
|
26
|
+
"hardware-stop": "hardware-stop";
|
|
27
|
+
"destructive-remote": "destructive-remote";
|
|
28
|
+
"destructive-local": "destructive-local";
|
|
29
|
+
"destructive-foreign": "destructive-foreign";
|
|
30
|
+
spawn: "spawn";
|
|
31
|
+
"spend-over-cap": "spend-over-cap";
|
|
32
|
+
"authority-config": "authority-config";
|
|
33
|
+
"human-verb": "human-verb";
|
|
34
|
+
}>;
|
|
35
|
+
actor: z.ZodEnum<{
|
|
36
|
+
"owner-terminal": "owner-terminal";
|
|
37
|
+
"owner-remote": "owner-remote";
|
|
38
|
+
coordinator: "coordinator";
|
|
39
|
+
worker: "worker";
|
|
40
|
+
headless: "headless";
|
|
41
|
+
automation: "automation";
|
|
42
|
+
}>;
|
|
43
|
+
verdict: z.ZodEnum<{
|
|
44
|
+
allow: "allow";
|
|
45
|
+
gate: "gate";
|
|
46
|
+
deny: "deny";
|
|
47
|
+
}>;
|
|
48
|
+
resolvers: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
49
|
+
"owner-terminal": "owner-terminal";
|
|
50
|
+
"owner-remote": "owner-remote";
|
|
51
|
+
}>>>;
|
|
52
|
+
taintEscalates: z.ZodOptional<z.ZodBoolean>;
|
|
53
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
54
|
+
evidence: z.ZodArray<z.ZodEnum<{
|
|
55
|
+
"E-dec": "E-dec";
|
|
56
|
+
"E-gate": "E-gate";
|
|
57
|
+
"E-ref": "E-ref";
|
|
58
|
+
"E-byp": "E-byp";
|
|
59
|
+
"E-gh": "E-gh";
|
|
60
|
+
"E-npm": "E-npm";
|
|
61
|
+
"E-spn": "E-spn";
|
|
62
|
+
"E-prin": "E-prin";
|
|
63
|
+
"E-dev": "E-dev";
|
|
64
|
+
}>>;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
type Rule = z.infer<typeof ruleSchema>;
|
|
67
|
+
interface PolicyTable {
|
|
68
|
+
version: string;
|
|
69
|
+
rules: Rule[];
|
|
70
|
+
}
|
|
71
|
+
/** Validates a table: every (action, actor) pair exactly once, and only owner classes as gate resolvers. */
|
|
72
|
+
declare const policyTableSchema: z.ZodType<PolicyTable>;
|
|
73
|
+
|
|
74
|
+
interface AuthorityRequest {
|
|
75
|
+
action: ActionClass;
|
|
76
|
+
actor: {
|
|
77
|
+
class: ActorClass;
|
|
78
|
+
id: string;
|
|
79
|
+
};
|
|
80
|
+
tainted: boolean;
|
|
81
|
+
subject: Record<string, string>;
|
|
82
|
+
}
|
|
83
|
+
type Decision = {
|
|
84
|
+
verdict: "allow";
|
|
85
|
+
ruleId: string;
|
|
86
|
+
} | {
|
|
87
|
+
verdict: "gate";
|
|
88
|
+
ruleId: string;
|
|
89
|
+
resolvers: ResolverClass[];
|
|
90
|
+
reason: string;
|
|
91
|
+
} | {
|
|
92
|
+
verdict: "deny";
|
|
93
|
+
ruleId: string | null;
|
|
94
|
+
reason: string;
|
|
95
|
+
};
|
|
96
|
+
/** Decides one request against a table. Pure: no clock, no environment, and no match means deny. */
|
|
97
|
+
declare function evaluate(table: PolicyTable, request: AuthorityRequest): Decision;
|
|
98
|
+
/** Whether a resolver may resolve the gate a rule opens. Agents, automation and tainted sessions never may. */
|
|
99
|
+
declare function canResolve(table: PolicyTable, ruleId: string, resolver: {
|
|
100
|
+
class: ActorClass;
|
|
101
|
+
tainted: boolean;
|
|
102
|
+
}): boolean;
|
|
103
|
+
|
|
104
|
+
/** The owner-approved decision table, validated on load. The same data ships as `@titan-design/authority/table.json`. */
|
|
105
|
+
declare const DEFAULT_TABLE: PolicyTable;
|
|
106
|
+
|
|
107
|
+
export { ACTION_CLASSES, ACTOR_CLASSES, type ActionClass, type ActorClass, type AuthorityRequest, DEFAULT_TABLE, type Decision, EVIDENCE_KINDS, type EvidenceKind, type PolicyTable, RESOLVER_CLASSES, type ResolverClass, type Rule, VERDICTS, type Verdict, canResolve, evaluate, policyTableSchema };
|