@openvtc/trust-tasks 0.22.5 → 0.22.7
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/CHANGELOG.md +80 -0
- package/dist/_shared/components.d.ts +434 -1
- package/dist/_shared/components.d.ts.map +1 -1
- package/dist/acl/_shared/0.1/acl-entry.d.ts +1 -1
- package/dist/acl/_shared/0.1/acl-entry.d.ts.map +1 -1
- package/dist/acl/_shared/0.2/acl-entry.d.ts +22 -0
- package/dist/acl/_shared/0.2/acl-entry.d.ts.map +1 -0
- package/dist/acl/_shared/0.2/acl-entry.js +6 -0
- package/dist/acl/_shared/0.2/acl-entry.js.map +1 -0
- package/dist/acl/change-role/0.1/payload.d.ts +1 -1
- package/dist/acl/change-role/0.1/payload.d.ts.map +1 -1
- package/dist/acl/change-role/0.2/payload.d.ts +1679 -0
- package/dist/acl/change-role/0.2/payload.d.ts.map +1 -0
- package/dist/acl/change-role/0.2/payload.js +955 -0
- package/dist/acl/change-role/0.2/payload.js.map +1 -0
- package/dist/acl/grant/0.1/payload.d.ts +1 -1
- package/dist/acl/grant/0.1/payload.d.ts.map +1 -1
- package/dist/acl/grant/0.2/payload.d.ts +1649 -0
- package/dist/acl/grant/0.2/payload.d.ts.map +1 -0
- package/dist/acl/grant/0.2/payload.js +942 -0
- package/dist/acl/grant/0.2/payload.js.map +1 -0
- package/dist/acl/list/0.1/payload.d.ts +1 -1
- package/dist/acl/list/0.1/payload.d.ts.map +1 -1
- package/dist/acl/list/0.2/payload.d.ts +1853 -0
- package/dist/acl/list/0.2/payload.d.ts.map +1 -0
- package/dist/acl/list/0.2/payload.js +1041 -0
- package/dist/acl/list/0.2/payload.js.map +1 -0
- package/dist/acl/revoke/0.1/payload.d.ts +1 -1
- package/dist/acl/revoke/0.1/payload.d.ts.map +1 -1
- package/dist/acl/revoke/0.2/payload.d.ts +1844 -0
- package/dist/acl/revoke/0.2/payload.d.ts.map +1 -0
- package/dist/acl/revoke/0.2/payload.js +1052 -0
- package/dist/acl/revoke/0.2/payload.js.map +1 -0
- package/dist/acl/show/0.1/payload.d.ts +1 -1
- package/dist/acl/show/0.1/payload.d.ts.map +1 -1
- package/dist/acl/show/0.2/payload.d.ts +1689 -0
- package/dist/acl/show/0.2/payload.d.ts.map +1 -0
- package/dist/acl/show/0.2/payload.js +968 -0
- package/dist/acl/show/0.2/payload.js.map +1 -0
- package/dist/acl/swap-key/0.1/payload.d.ts +1 -1
- package/dist/acl/swap-key/0.1/payload.d.ts.map +1 -1
- package/dist/acl/update/0.1/payload.d.ts +1 -1
- package/dist/acl/update/0.1/payload.d.ts.map +1 -1
- package/dist/acl/update/0.2/payload.d.ts +1784 -0
- package/dist/acl/update/0.2/payload.d.ts.map +1 -0
- package/dist/acl/update/0.2/payload.js +1005 -0
- package/dist/acl/update/0.2/payload.js.map +1 -0
- package/dist/auth/signing-key/authorize/0.1/payload.d.ts +199 -0
- package/dist/auth/signing-key/authorize/0.1/payload.d.ts.map +1 -0
- package/dist/auth/signing-key/authorize/0.1/payload.js +108 -0
- package/dist/auth/signing-key/authorize/0.1/payload.js.map +1 -0
- package/dist/auth/signing-key/enroll/0.2/payload.d.ts +569 -0
- package/dist/auth/signing-key/enroll/0.2/payload.d.ts.map +1 -0
- package/dist/auth/signing-key/enroll/0.2/payload.js +315 -0
- package/dist/auth/signing-key/enroll/0.2/payload.js.map +1 -0
- package/dist/auth/step-up/approve-request/0.4/payload.d.ts +672 -0
- package/dist/auth/step-up/approve-request/0.4/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approve-request/0.4/payload.js +373 -0
- package/dist/auth/step-up/approve-request/0.4/payload.js.map +1 -0
- package/dist/auth/step-up/approve-response/0.6/payload.d.ts +974 -0
- package/dist/auth/step-up/approve-response/0.6/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approve-response/0.6/payload.js +552 -0
- package/dist/auth/step-up/approve-response/0.6/payload.js.map +1 -0
- package/dist/auth/step-up/approver/_shared/0.1/approver.d.ts +16 -0
- package/dist/auth/step-up/approver/_shared/0.1/approver.d.ts.map +1 -0
- package/dist/auth/step-up/approver/_shared/0.1/approver.js +6 -0
- package/dist/auth/step-up/approver/_shared/0.1/approver.js.map +1 -0
- package/dist/auth/step-up/approver/attest/0.1/payload.d.ts +174 -0
- package/dist/auth/step-up/approver/attest/0.1/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approver/attest/0.1/payload.js +97 -0
- package/dist/auth/step-up/approver/attest/0.1/payload.js.map +1 -0
- package/dist/auth/step-up/approver/enroll/0.1/payload.d.ts +503 -0
- package/dist/auth/step-up/approver/enroll/0.1/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approver/enroll/0.1/payload.js +285 -0
- package/dist/auth/step-up/approver/enroll/0.1/payload.js.map +1 -0
- package/dist/auth/step-up/approver/invite/0.1/payload.d.ts +375 -0
- package/dist/auth/step-up/approver/invite/0.1/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approver/invite/0.1/payload.js +200 -0
- package/dist/auth/step-up/approver/invite/0.1/payload.js.map +1 -0
- package/dist/auth/step-up/approver/list/0.1/payload.d.ts +477 -0
- package/dist/auth/step-up/approver/list/0.1/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approver/list/0.1/payload.js +272 -0
- package/dist/auth/step-up/approver/list/0.1/payload.js.map +1 -0
- package/dist/auth/step-up/approver/redeem/finish/0.1/payload.d.ts +512 -0
- package/dist/auth/step-up/approver/redeem/finish/0.1/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approver/redeem/finish/0.1/payload.js +290 -0
- package/dist/auth/step-up/approver/redeem/finish/0.1/payload.js.map +1 -0
- package/dist/auth/step-up/approver/redeem/start/0.1/payload.d.ts +343 -0
- package/dist/auth/step-up/approver/redeem/start/0.1/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approver/redeem/start/0.1/payload.js +187 -0
- package/dist/auth/step-up/approver/redeem/start/0.1/payload.js.map +1 -0
- package/dist/auth/step-up/approver/revoke/0.1/payload.d.ts +534 -0
- package/dist/auth/step-up/approver/revoke/0.1/payload.d.ts.map +1 -0
- package/dist/auth/step-up/approver/revoke/0.1/payload.js +301 -0
- package/dist/auth/step-up/approver/revoke/0.1/payload.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -1
- package/dist/task-consent/decision/0.2/payload.d.ts +775 -0
- package/dist/task-consent/decision/0.2/payload.d.ts.map +1 -0
- package/dist/task-consent/decision/0.2/payload.js +450 -0
- package/dist/task-consent/decision/0.2/payload.js.map +1 -0
- package/dist/vtc/admin/actions/_shared/0.1/action.d.ts +24 -0
- package/dist/vtc/admin/actions/_shared/0.1/action.d.ts.map +1 -0
- package/dist/vtc/admin/actions/_shared/0.1/action.js +6 -0
- package/dist/vtc/admin/actions/_shared/0.1/action.js.map +1 -0
- package/dist/vtc/admin/actions/acknowledge/0.1/payload.d.ts +1012 -0
- package/dist/vtc/admin/actions/acknowledge/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/admin/actions/acknowledge/0.1/payload.js +636 -0
- package/dist/vtc/admin/actions/acknowledge/0.1/payload.js.map +1 -0
- package/dist/vtc/admin/actions/cancel/0.1/payload.d.ts +1026 -0
- package/dist/vtc/admin/actions/cancel/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/admin/actions/cancel/0.1/payload.js +641 -0
- package/dist/vtc/admin/actions/cancel/0.1/payload.js.map +1 -0
- package/dist/vtc/admin/actions/list/0.1/payload.d.ts +1200 -0
- package/dist/vtc/admin/actions/list/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/admin/actions/list/0.1/payload.js +726 -0
- package/dist/vtc/admin/actions/list/0.1/payload.js.map +1 -0
- package/dist/vtc/admin/actions/show/0.1/payload.d.ts +1012 -0
- package/dist/vtc/admin/actions/show/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/admin/actions/show/0.1/payload.js +636 -0
- package/dist/vtc/admin/actions/show/0.1/payload.js.map +1 -0
- package/dist/vtc/install/claim/finish/0.3/payload.d.ts +379 -0
- package/dist/vtc/install/claim/finish/0.3/payload.d.ts.map +1 -0
- package/dist/vtc/install/claim/finish/0.3/payload.js +205 -0
- package/dist/vtc/install/claim/finish/0.3/payload.js.map +1 -0
- package/dist/vtc/install/claim/start/0.3/payload.d.ts +368 -0
- package/dist/vtc/install/claim/start/0.3/payload.d.ts.map +1 -0
- package/dist/vtc/install/claim/start/0.3/payload.js +201 -0
- package/dist/vtc/install/claim/start/0.3/payload.js.map +1 -0
- package/dist/vtc/members/authority-reduced-notice/0.1/payload.d.ts +208 -0
- package/dist/vtc/members/authority-reduced-notice/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/members/authority-reduced-notice/0.1/payload.js +112 -0
- package/dist/vtc/members/authority-reduced-notice/0.1/payload.js.map +1 -0
- package/dist/vtc/roles/_shared/0.1/role.d.ts +16 -0
- package/dist/vtc/roles/_shared/0.1/role.d.ts.map +1 -0
- package/dist/vtc/roles/_shared/0.1/role.js +6 -0
- package/dist/vtc/roles/_shared/0.1/role.js.map +1 -0
- package/dist/vtc/roles/define/0.1/payload.d.ts +703 -0
- package/dist/vtc/roles/define/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/roles/define/0.1/payload.js +371 -0
- package/dist/vtc/roles/define/0.1/payload.js.map +1 -0
- package/dist/vtc/roles/delete/0.1/payload.d.ts +281 -0
- package/dist/vtc/roles/delete/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/roles/delete/0.1/payload.js +152 -0
- package/dist/vtc/roles/delete/0.1/payload.js.map +1 -0
- package/dist/vtc/roles/list/0.1/payload.d.ts +639 -0
- package/dist/vtc/roles/list/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/roles/list/0.1/payload.js +345 -0
- package/dist/vtc/roles/list/0.1/payload.js.map +1 -0
- package/dist/vtc/roles/show/0.1/payload.d.ts +651 -0
- package/dist/vtc/roles/show/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/roles/show/0.1/payload.js +351 -0
- package/dist/vtc/roles/show/0.1/payload.js.map +1 -0
- package/package.json +1 -1
- package/src/_shared/components.ts +440 -1
- package/src/acl/_shared/0.1/acl-entry.ts +1 -1
- package/src/acl/_shared/0.2/acl-entry.ts +23 -0
- package/src/acl/change-role/0.1/payload.ts +1 -1
- package/src/acl/change-role/0.2/payload.ts +1011 -0
- package/src/acl/grant/0.1/payload.ts +1 -1
- package/src/acl/grant/0.2/payload.ts +990 -0
- package/src/acl/list/0.1/payload.ts +1 -1
- package/src/acl/list/0.2/payload.ts +1125 -0
- package/src/acl/revoke/0.1/payload.ts +1 -1
- package/src/acl/revoke/0.2/payload.ts +1122 -0
- package/src/acl/show/0.1/payload.ts +1 -1
- package/src/acl/show/0.2/payload.ts +1016 -0
- package/src/acl/swap-key/0.1/payload.ts +1 -1
- package/src/acl/update/0.1/payload.ts +1 -1
- package/src/acl/update/0.2/payload.ts +1094 -0
- package/src/auth/signing-key/authorize/0.1/payload.ts +141 -0
- package/src/auth/signing-key/enroll/0.2/payload.ts +365 -0
- package/src/auth/step-up/approve-request/0.4/payload.ts +461 -0
- package/src/auth/step-up/approve-response/0.6/payload.ts +648 -0
- package/src/auth/step-up/approver/_shared/0.1/approver.ts +17 -0
- package/src/auth/step-up/approver/attest/0.1/payload.ts +135 -0
- package/src/auth/step-up/approver/enroll/0.1/payload.ts +329 -0
- package/src/auth/step-up/approver/invite/0.1/payload.ts +258 -0
- package/src/auth/step-up/approver/list/0.1/payload.ts +318 -0
- package/src/auth/step-up/approver/redeem/finish/0.1/payload.ts +337 -0
- package/src/auth/step-up/approver/redeem/start/0.1/payload.ts +241 -0
- package/src/auth/step-up/approver/revoke/0.1/payload.ts +352 -0
- package/src/index.ts +33 -0
- package/src/task-consent/decision/0.2/payload.ts +537 -0
- package/src/vtc/admin/actions/_shared/0.1/action.ts +25 -0
- package/src/vtc/admin/actions/acknowledge/0.1/payload.ts +671 -0
- package/src/vtc/admin/actions/cancel/0.1/payload.ts +680 -0
- package/src/vtc/admin/actions/list/0.1/payload.ts +795 -0
- package/src/vtc/admin/actions/show/0.1/payload.ts +671 -0
- package/src/vtc/install/claim/finish/0.3/payload.ts +253 -0
- package/src/vtc/install/claim/start/0.3/payload.ts +256 -0
- package/src/vtc/members/authority-reduced-notice/0.1/payload.ts +162 -0
- package/src/vtc/roles/_shared/0.1/role.ts +17 -0
- package/src/vtc/roles/define/0.1/payload.ts +435 -0
- package/src/vtc/roles/delete/0.1/payload.ts +200 -0
- package/src/vtc/roles/list/0.1/payload.ts +389 -0
- package/src/vtc/roles/show/0.1/payload.ts +399 -0
|
@@ -0,0 +1,1784 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated by scripts/build-ts-bindings.mjs — DO NOT EDIT BY HAND.
|
|
3
|
+
* Source: specs/acl/update/0.2/payload.schema.json
|
|
4
|
+
*/
|
|
5
|
+
import type { AclEntry_AclV0_2 as AclEntry, ApproveCapabilityScope, ApproveCapabilityScopeListed, AuthorityScope, AuthorityScopeAll, AuthorityScopeContexts, AuthorityScopeNone, Capability_AclV0_2 as Capability, CapabilityGrant, CapabilityRef, CapabilityScope, CapabilityScopeCeiling, CapabilityScopeListed, CapabilityScopeNone, ContextPath, Ext, KeyScope, KeyScopeAll, KeyScopeListed, KeyScopeNone, ResourceQualifier } from "../../../_shared/components.js";
|
|
6
|
+
/**
|
|
7
|
+
* Amend the non-role attributes of an existing AclEntry 0.2: its act scope (widening only), approve scope, capability scope, approvable-capability scope, key scope, label, expiry or step-up requirement. Every member REPLACES the stored value; an omitted member leaves it unchanged. Role changes are NOT expressible here — they go through acl/change-role, which requires the current role as a compare-and-swap. `delegatedBy` and the provenance timestamps are maintainer-populated and not settable.
|
|
8
|
+
*/
|
|
9
|
+
export interface ACLUpdate02Payload {
|
|
10
|
+
/**
|
|
11
|
+
* VID of the entry to amend. The entry MUST already exist; this task does not create one (use acl/grant).
|
|
12
|
+
*/
|
|
13
|
+
subject: string;
|
|
14
|
+
/**
|
|
15
|
+
* Replacement act scope, in the same explicit form as the entry's (`all`, `none`, or a non-empty context list). A replacement that WIDENS or equals the stored scope is accepted, subject to the granter bound. NARROWING THE ACT SCOPE IS A REVOCATION and a consumer MUST refuse it here with `narrowingNotPermitted`, directing the caller to acl/revoke, so that every removal of where a subject may act passes through the task that is audited and reasoned as a revocation.
|
|
16
|
+
*/
|
|
17
|
+
act?: AuthorityScope;
|
|
18
|
+
/**
|
|
19
|
+
* Replacement approve scope. To withdraw approve authority entirely, send `{"scope": "none"}` — there is no null form, because the explicit value is the only spelling that cannot be misread. Widening is an escalation vector (a subject able to approve can ratify operations it could not authorize) and is bounded by the granter's own approve authority. Narrowing is accepted here and is a privilege reduction (see the specification).
|
|
20
|
+
*/
|
|
21
|
+
approve?: AuthorityScope;
|
|
22
|
+
/**
|
|
23
|
+
* Replacement capability scope, applied wholesale, in the same explicit form as the entry's. Omitted leaves it unchanged. `{"scope": "ceiling"}` returns the entry to its role's full ceiling — a privilege INCREASE, bounded and gated like any widening; `{"scope": "none"}` removes every capability; `listed` states the exact set. There is no null form. Every listed capability is checked as on a grant (registry, ceiling, additive, granter bound). A replacement that removes a capability the entry held is a privilege reduction.
|
|
24
|
+
*/
|
|
25
|
+
capabilities?: CapabilityScope;
|
|
26
|
+
/**
|
|
27
|
+
* Replacement approvable-capability scope, applied wholesale. Omitted leaves it unchanged. `{"scope": "ceiling"}` lets the subject approve its role's full approve ceiling within its approve scope (a privilege increase); `{"scope": "none"}` withdraws it; `listed` states the exact set. There is no null form. Bounded by the granter's own approve authority.
|
|
28
|
+
*/
|
|
29
|
+
approveCapabilities?: ApproveCapabilityScope;
|
|
30
|
+
/**
|
|
31
|
+
* Replacement key scope, applied wholesale. Omitted leaves it unchanged. `{"scope": "all"}` lets the subject reach every key within its act scope again — a privilege increase a consumer SHOULD gate like clearing `expiresAt`; `{"scope": "none"}` removes every key; `listed` states the exact set. There is no null form. A replacement that narrows the stored key scope IS a privilege reduction: it is accepted here, because acl/revoke/0.2 narrows only the act scope, but the consumer MUST audit it as a reduction and apply it at the subject's next authorization decision.
|
|
32
|
+
*/
|
|
33
|
+
keys?: KeyScope;
|
|
34
|
+
/**
|
|
35
|
+
* Replacement human-readable label. Explicit `null` clears it. Omitted leaves it unchanged.
|
|
36
|
+
*/
|
|
37
|
+
label?: string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Replacement expiry. Explicit `null` makes the entry permanent — a privilege increase, which a consumer SHOULD gate at least as strictly as the original grant, and which is refused where the granter's own entry expires.
|
|
40
|
+
*/
|
|
41
|
+
expiresAt?: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Replacement per-entry step-up configuration. Same additive-only rule as on the entry itself: it MAY raise the assurance required of this subject above the system floor but MUST NOT lower it.
|
|
44
|
+
*/
|
|
45
|
+
stepUp?: {
|
|
46
|
+
/**
|
|
47
|
+
* VID that ratifies step-up for this subject. `null` clears it.
|
|
48
|
+
*/
|
|
49
|
+
approver?: string | null;
|
|
50
|
+
/**
|
|
51
|
+
* Minimum step-up mode. `null` clears the per-entry override.
|
|
52
|
+
*/
|
|
53
|
+
require?: "self" | "delegated" | null;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Optional human-readable rationale, recorded with the change.
|
|
57
|
+
*/
|
|
58
|
+
reason?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Ecosystem-defined extension members per SPEC.md §4.5.1.
|
|
61
|
+
*/
|
|
62
|
+
ext?: Ext;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The success response to an acl/update/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/update/0.2#response.
|
|
66
|
+
*/
|
|
67
|
+
export interface ACLUpdate02ResponsePayload {
|
|
68
|
+
/**
|
|
69
|
+
* The realized entry the maintainer now holds, after the amendment.
|
|
70
|
+
*/
|
|
71
|
+
entry: AclEntry;
|
|
72
|
+
/**
|
|
73
|
+
* Ecosystem-defined extension members per SPEC.md §4.5.1.
|
|
74
|
+
*/
|
|
75
|
+
ext?: Ext;
|
|
76
|
+
}
|
|
77
|
+
/** Shared definitions this specification references, re-exported under the names it used to declare them with. */
|
|
78
|
+
export type { AclEntry, ApproveCapabilityScope, ApproveCapabilityScopeListed, AuthorityScope, AuthorityScopeAll, AuthorityScopeContexts, AuthorityScopeNone, Capability, CapabilityGrant, CapabilityRef, CapabilityScope, CapabilityScopeCeiling, CapabilityScopeListed, CapabilityScopeNone, ContextPath, Ext, KeyScope, KeyScopeAll, KeyScopeListed, KeyScopeNone, ResourceQualifier };
|
|
79
|
+
/** Trust Task type URI. */
|
|
80
|
+
export declare const TYPE_URI: "https://trusttasks.org/spec/acl/update/0.2";
|
|
81
|
+
/** Stable alias for this specification's request payload shape. */
|
|
82
|
+
export type Payload = ACLUpdate02Payload;
|
|
83
|
+
/** Trust Task response type URI (request type URI + "#response"). */
|
|
84
|
+
export declare const RESPONSE_TYPE_URI: "https://trusttasks.org/spec/acl/update/0.2#response";
|
|
85
|
+
/** Stable alias for this specification's success-response payload shape. */
|
|
86
|
+
export type Response = ACLUpdate02ResponsePayload;
|
|
87
|
+
/**
|
|
88
|
+
* This specification's payload schema, as a value.
|
|
89
|
+
*
|
|
90
|
+
* SPEC.md §7.2 item 2 is performed against this. It is shipped as data
|
|
91
|
+
* rather than only as a `.json` file because TypeScript types are erased
|
|
92
|
+
* at runtime: without a schema a consumer has nothing to validate, and
|
|
93
|
+
* every REQUIRED payload member is optional in practice. Cross-file
|
|
94
|
+
* `$ref`s are already inlined, so it needs no resolver.
|
|
95
|
+
*/
|
|
96
|
+
export declare const PAYLOAD_SCHEMA: {
|
|
97
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
98
|
+
readonly $id: "https://trusttasks.org/spec/acl/update/0.2";
|
|
99
|
+
readonly title: "ACL Update 0.2 — payload";
|
|
100
|
+
readonly description: "Amend the non-role attributes of an existing AclEntry 0.2: its act scope (widening only), approve scope, capability scope, approvable-capability scope, key scope, label, expiry or step-up requirement. Every member REPLACES the stored value; an omitted member leaves it unchanged. Role changes are NOT expressible here — they go through acl/change-role, which requires the current role as a compare-and-swap. `delegatedBy` and the provenance timestamps are maintainer-populated and not settable.";
|
|
101
|
+
readonly type: "object";
|
|
102
|
+
readonly additionalProperties: false;
|
|
103
|
+
readonly required: readonly ["subject"];
|
|
104
|
+
readonly properties: {
|
|
105
|
+
readonly subject: {
|
|
106
|
+
readonly type: "string";
|
|
107
|
+
readonly minLength: 1;
|
|
108
|
+
readonly description: "VID of the entry to amend. The entry MUST already exist; this task does not create one (use acl/grant).";
|
|
109
|
+
};
|
|
110
|
+
readonly act: {
|
|
111
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
112
|
+
readonly description: "Replacement act scope, in the same explicit form as the entry's (`all`, `none`, or a non-empty context list). A replacement that WIDENS or equals the stored scope is accepted, subject to the granter bound. NARROWING THE ACT SCOPE IS A REVOCATION and a consumer MUST refuse it here with `narrowingNotPermitted`, directing the caller to acl/revoke, so that every removal of where a subject may act passes through the task that is audited and reasoned as a revocation.";
|
|
113
|
+
};
|
|
114
|
+
readonly approve: {
|
|
115
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
116
|
+
readonly description: "Replacement approve scope. To withdraw approve authority entirely, send `{\"scope\": \"none\"}` — there is no null form, because the explicit value is the only spelling that cannot be misread. Widening is an escalation vector (a subject able to approve can ratify operations it could not authorize) and is bounded by the granter's own approve authority. Narrowing is accepted here and is a privilege reduction (see the specification).";
|
|
117
|
+
};
|
|
118
|
+
readonly capabilities: {
|
|
119
|
+
readonly $ref: "#/$defs/CapabilityScope";
|
|
120
|
+
readonly description: "Replacement capability scope, applied wholesale, in the same explicit form as the entry's. Omitted leaves it unchanged. `{\"scope\": \"ceiling\"}` returns the entry to its role's full ceiling — a privilege INCREASE, bounded and gated like any widening; `{\"scope\": \"none\"}` removes every capability; `listed` states the exact set. There is no null form. Every listed capability is checked as on a grant (registry, ceiling, additive, granter bound). A replacement that removes a capability the entry held is a privilege reduction.";
|
|
121
|
+
};
|
|
122
|
+
readonly approveCapabilities: {
|
|
123
|
+
readonly $ref: "#/$defs/ApproveCapabilityScope";
|
|
124
|
+
readonly description: "Replacement approvable-capability scope, applied wholesale. Omitted leaves it unchanged. `{\"scope\": \"ceiling\"}` lets the subject approve its role's full approve ceiling within its approve scope (a privilege increase); `{\"scope\": \"none\"}` withdraws it; `listed` states the exact set. There is no null form. Bounded by the granter's own approve authority.";
|
|
125
|
+
};
|
|
126
|
+
readonly keys: {
|
|
127
|
+
readonly $ref: "#/$defs/KeyScope";
|
|
128
|
+
readonly description: "Replacement key scope, applied wholesale. Omitted leaves it unchanged. `{\"scope\": \"all\"}` lets the subject reach every key within its act scope again — a privilege increase a consumer SHOULD gate like clearing `expiresAt`; `{\"scope\": \"none\"}` removes every key; `listed` states the exact set. There is no null form. A replacement that narrows the stored key scope IS a privilege reduction: it is accepted here, because acl/revoke/0.2 narrows only the act scope, but the consumer MUST audit it as a reduction and apply it at the subject's next authorization decision.";
|
|
129
|
+
};
|
|
130
|
+
readonly label: {
|
|
131
|
+
readonly type: readonly ["string", "null"];
|
|
132
|
+
readonly maxLength: 256;
|
|
133
|
+
readonly description: "Replacement human-readable label. Explicit `null` clears it. Omitted leaves it unchanged.";
|
|
134
|
+
};
|
|
135
|
+
readonly expiresAt: {
|
|
136
|
+
readonly type: readonly ["string", "null"];
|
|
137
|
+
readonly format: "date-time";
|
|
138
|
+
readonly description: "Replacement expiry. Explicit `null` makes the entry permanent — a privilege increase, which a consumer SHOULD gate at least as strictly as the original grant, and which is refused where the granter's own entry expires.";
|
|
139
|
+
};
|
|
140
|
+
readonly stepUp: {
|
|
141
|
+
readonly type: "object";
|
|
142
|
+
readonly additionalProperties: false;
|
|
143
|
+
readonly description: "Replacement per-entry step-up configuration. Same additive-only rule as on the entry itself: it MAY raise the assurance required of this subject above the system floor but MUST NOT lower it.";
|
|
144
|
+
readonly properties: {
|
|
145
|
+
readonly approver: {
|
|
146
|
+
readonly type: readonly ["string", "null"];
|
|
147
|
+
readonly description: "VID that ratifies step-up for this subject. `null` clears it.";
|
|
148
|
+
};
|
|
149
|
+
readonly require: {
|
|
150
|
+
readonly type: readonly ["string", "null"];
|
|
151
|
+
readonly enum: readonly ["self", "delegated", null];
|
|
152
|
+
readonly description: "Minimum step-up mode. `null` clears the per-entry override.";
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
readonly reason: {
|
|
157
|
+
readonly type: "string";
|
|
158
|
+
readonly maxLength: 1024;
|
|
159
|
+
readonly description: "Optional human-readable rationale, recorded with the change.";
|
|
160
|
+
};
|
|
161
|
+
readonly ext: {
|
|
162
|
+
readonly $ref: "#/$defs/Ext";
|
|
163
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
readonly $defs: {
|
|
167
|
+
readonly Response: {
|
|
168
|
+
readonly $anchor: "response";
|
|
169
|
+
readonly title: "ACL Update 0.2 — response payload";
|
|
170
|
+
readonly description: "The success response to an acl/update/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/update/0.2#response.";
|
|
171
|
+
readonly type: "object";
|
|
172
|
+
readonly additionalProperties: false;
|
|
173
|
+
readonly required: readonly ["entry"];
|
|
174
|
+
readonly properties: {
|
|
175
|
+
readonly entry: {
|
|
176
|
+
readonly $ref: "#/$defs/AclEntry";
|
|
177
|
+
readonly description: "The realized entry the maintainer now holds, after the amendment.";
|
|
178
|
+
};
|
|
179
|
+
readonly ext: {
|
|
180
|
+
readonly $ref: "#/$defs/Ext";
|
|
181
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
readonly Ext: {
|
|
186
|
+
readonly title: "Ext";
|
|
187
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
188
|
+
readonly type: "object";
|
|
189
|
+
readonly minProperties: 1;
|
|
190
|
+
readonly additionalProperties: true;
|
|
191
|
+
readonly propertyNames: {
|
|
192
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
readonly AclEntry: {
|
|
196
|
+
readonly title: "AclEntry";
|
|
197
|
+
readonly description: "One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).\n\nThe act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer \"may this subject do X\"; `approve` + `approveCapabilities` answer \"may this subject ratify someone else doing X\". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.";
|
|
198
|
+
readonly type: "object";
|
|
199
|
+
readonly additionalProperties: false;
|
|
200
|
+
readonly required: readonly ["subject", "role", "act", "keys", "capabilities"];
|
|
201
|
+
readonly properties: {
|
|
202
|
+
readonly subject: {
|
|
203
|
+
readonly type: "string";
|
|
204
|
+
readonly minLength: 1;
|
|
205
|
+
readonly description: "VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.";
|
|
206
|
+
};
|
|
207
|
+
readonly role: {
|
|
208
|
+
readonly type: "string";
|
|
209
|
+
readonly minLength: 1;
|
|
210
|
+
readonly description: "Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.";
|
|
211
|
+
};
|
|
212
|
+
readonly act: {
|
|
213
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
214
|
+
readonly description: "REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{\"scope\": \"all\"}` (unrestricted — every context the maintainer has), `{\"scope\": \"none\"}` (may act nowhere), or `{\"scope\": \"contexts\", \"contexts\": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.";
|
|
215
|
+
};
|
|
216
|
+
readonly approve: {
|
|
217
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
218
|
+
readonly description: "OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{\"scope\": \"none\"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.";
|
|
219
|
+
};
|
|
220
|
+
readonly capabilities: {
|
|
221
|
+
readonly $ref: "#/$defs/CapabilityScope";
|
|
222
|
+
readonly description: "REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{\"scope\": \"ceiling\"}` (the role's full ceiling, unnarrowed), `{\"scope\": \"none\"}` (no capabilities), or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.";
|
|
223
|
+
};
|
|
224
|
+
readonly approveCapabilities: {
|
|
225
|
+
readonly $ref: "#/$defs/ApproveCapabilityScope";
|
|
226
|
+
readonly description: "OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{\"scope\": \"ceiling\"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{\"scope\": \"none\"}`, or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{\"scope\": \"none\"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.";
|
|
227
|
+
};
|
|
228
|
+
readonly delegatedBy: {
|
|
229
|
+
readonly type: "string";
|
|
230
|
+
readonly minLength: 1;
|
|
231
|
+
readonly description: "VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).";
|
|
232
|
+
};
|
|
233
|
+
readonly keys: {
|
|
234
|
+
readonly $ref: "#/$defs/KeyScope";
|
|
235
|
+
readonly description: "REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{\"scope\": \"all\"}` (every key the entry's act scope reaches), `{\"scope\": \"none\"}` (no keys), or `{\"scope\": \"listed\", \"keys\": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{\"scope\": \"none\"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.";
|
|
236
|
+
};
|
|
237
|
+
readonly label: {
|
|
238
|
+
readonly type: "string";
|
|
239
|
+
readonly maxLength: 256;
|
|
240
|
+
readonly description: "Optional human-readable label. Confers nothing.";
|
|
241
|
+
};
|
|
242
|
+
readonly createdAt: {
|
|
243
|
+
readonly type: "string";
|
|
244
|
+
readonly format: "date-time";
|
|
245
|
+
};
|
|
246
|
+
readonly createdBy: {
|
|
247
|
+
readonly type: "string";
|
|
248
|
+
readonly description: "VID of the party that originally wrote this entry.";
|
|
249
|
+
};
|
|
250
|
+
readonly updatedAt: {
|
|
251
|
+
readonly type: "string";
|
|
252
|
+
readonly format: "date-time";
|
|
253
|
+
};
|
|
254
|
+
readonly updatedBy: {
|
|
255
|
+
readonly type: "string";
|
|
256
|
+
readonly description: "VID of the party that last modified this entry.";
|
|
257
|
+
};
|
|
258
|
+
readonly expiresAt: {
|
|
259
|
+
readonly type: "string";
|
|
260
|
+
readonly format: "date-time";
|
|
261
|
+
readonly description: "Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.";
|
|
262
|
+
};
|
|
263
|
+
readonly stepUp: {
|
|
264
|
+
readonly type: "object";
|
|
265
|
+
readonly additionalProperties: false;
|
|
266
|
+
readonly description: "Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.";
|
|
267
|
+
readonly properties: {
|
|
268
|
+
readonly approver: {
|
|
269
|
+
readonly type: "string";
|
|
270
|
+
readonly description: "VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.";
|
|
271
|
+
};
|
|
272
|
+
readonly require: {
|
|
273
|
+
readonly type: "string";
|
|
274
|
+
readonly enum: readonly ["self", "delegated"];
|
|
275
|
+
readonly description: "Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).";
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
};
|
|
279
|
+
readonly ext: {
|
|
280
|
+
readonly $ref: "#/$defs/Ext";
|
|
281
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.";
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
readonly KeyScope: {
|
|
286
|
+
readonly title: "KeyScope";
|
|
287
|
+
readonly description: "An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.";
|
|
288
|
+
readonly oneOf: readonly [{
|
|
289
|
+
readonly $ref: "#/$defs/KeyScopeAll";
|
|
290
|
+
}, {
|
|
291
|
+
readonly $ref: "#/$defs/KeyScopeNone";
|
|
292
|
+
}, {
|
|
293
|
+
readonly $ref: "#/$defs/KeyScopeListed";
|
|
294
|
+
}];
|
|
295
|
+
};
|
|
296
|
+
readonly KeyScopeListed: {
|
|
297
|
+
readonly title: "KeyScopeListed";
|
|
298
|
+
readonly description: "Exactly the listed keys, intersected with the entry's act scope.";
|
|
299
|
+
readonly type: "object";
|
|
300
|
+
readonly additionalProperties: false;
|
|
301
|
+
readonly required: readonly ["scope", "keys"];
|
|
302
|
+
readonly properties: {
|
|
303
|
+
readonly scope: {
|
|
304
|
+
readonly const: "listed";
|
|
305
|
+
};
|
|
306
|
+
readonly keys: {
|
|
307
|
+
readonly type: "array";
|
|
308
|
+
readonly minItems: 1;
|
|
309
|
+
readonly uniqueItems: true;
|
|
310
|
+
readonly items: {
|
|
311
|
+
readonly type: "string";
|
|
312
|
+
readonly minLength: 1;
|
|
313
|
+
readonly maxLength: 512;
|
|
314
|
+
};
|
|
315
|
+
readonly description: "Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).";
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
};
|
|
319
|
+
readonly KeyScopeNone: {
|
|
320
|
+
readonly title: "KeyScopeNone";
|
|
321
|
+
readonly description: "No keys.";
|
|
322
|
+
readonly type: "object";
|
|
323
|
+
readonly additionalProperties: false;
|
|
324
|
+
readonly required: readonly ["scope"];
|
|
325
|
+
readonly properties: {
|
|
326
|
+
readonly scope: {
|
|
327
|
+
readonly const: "none";
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
};
|
|
331
|
+
readonly KeyScopeAll: {
|
|
332
|
+
readonly title: "KeyScopeAll";
|
|
333
|
+
readonly description: "Every key the entry's act scope reaches.";
|
|
334
|
+
readonly type: "object";
|
|
335
|
+
readonly additionalProperties: false;
|
|
336
|
+
readonly required: readonly ["scope"];
|
|
337
|
+
readonly properties: {
|
|
338
|
+
readonly scope: {
|
|
339
|
+
readonly const: "all";
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
readonly ApproveCapabilityScope: {
|
|
344
|
+
readonly title: "ApproveCapabilityScope";
|
|
345
|
+
readonly description: "An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.";
|
|
346
|
+
readonly oneOf: readonly [{
|
|
347
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
348
|
+
}, {
|
|
349
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
350
|
+
}, {
|
|
351
|
+
readonly $ref: "#/$defs/ApproveCapabilityScopeListed";
|
|
352
|
+
}];
|
|
353
|
+
};
|
|
354
|
+
readonly ApproveCapabilityScopeListed: {
|
|
355
|
+
readonly title: "ApproveCapabilityScopeListed";
|
|
356
|
+
readonly description: "Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.";
|
|
357
|
+
readonly type: "object";
|
|
358
|
+
readonly additionalProperties: false;
|
|
359
|
+
readonly required: readonly ["scope", "grants"];
|
|
360
|
+
readonly properties: {
|
|
361
|
+
readonly scope: {
|
|
362
|
+
readonly const: "listed";
|
|
363
|
+
};
|
|
364
|
+
readonly grants: {
|
|
365
|
+
readonly type: "array";
|
|
366
|
+
readonly minItems: 1;
|
|
367
|
+
readonly items: {
|
|
368
|
+
readonly $ref: "#/$defs/CapabilityRef";
|
|
369
|
+
};
|
|
370
|
+
readonly description: "Non-empty list of approvable capabilities. An empty array is invalid.";
|
|
371
|
+
};
|
|
372
|
+
};
|
|
373
|
+
};
|
|
374
|
+
readonly CapabilityRef: {
|
|
375
|
+
readonly title: "CapabilityRef";
|
|
376
|
+
readonly description: "A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.";
|
|
377
|
+
readonly type: "object";
|
|
378
|
+
readonly additionalProperties: false;
|
|
379
|
+
readonly required: readonly ["capability"];
|
|
380
|
+
readonly properties: {
|
|
381
|
+
readonly capability: {
|
|
382
|
+
readonly $ref: "#/$defs/Capability";
|
|
383
|
+
};
|
|
384
|
+
readonly resource: {
|
|
385
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
386
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
};
|
|
390
|
+
readonly ResourceQualifier: {
|
|
391
|
+
readonly title: "ResourceQualifier";
|
|
392
|
+
readonly description: "Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.";
|
|
393
|
+
readonly type: "string";
|
|
394
|
+
readonly minLength: 1;
|
|
395
|
+
readonly maxLength: 512;
|
|
396
|
+
};
|
|
397
|
+
readonly Capability: {
|
|
398
|
+
readonly title: "Capability";
|
|
399
|
+
readonly description: "Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.";
|
|
400
|
+
readonly type: "string";
|
|
401
|
+
readonly minLength: 1;
|
|
402
|
+
readonly maxLength: 128;
|
|
403
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)*$";
|
|
404
|
+
};
|
|
405
|
+
readonly CapabilityScopeNone: {
|
|
406
|
+
readonly title: "CapabilityScopeNone";
|
|
407
|
+
readonly description: "No capabilities on this axis.";
|
|
408
|
+
readonly type: "object";
|
|
409
|
+
readonly additionalProperties: false;
|
|
410
|
+
readonly required: readonly ["scope"];
|
|
411
|
+
readonly properties: {
|
|
412
|
+
readonly scope: {
|
|
413
|
+
readonly const: "none";
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
};
|
|
417
|
+
readonly CapabilityScopeCeiling: {
|
|
418
|
+
readonly title: "CapabilityScopeCeiling";
|
|
419
|
+
readonly description: "The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of \"no narrowing\".";
|
|
420
|
+
readonly type: "object";
|
|
421
|
+
readonly additionalProperties: false;
|
|
422
|
+
readonly required: readonly ["scope"];
|
|
423
|
+
readonly properties: {
|
|
424
|
+
readonly scope: {
|
|
425
|
+
readonly const: "ceiling";
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
readonly CapabilityScope: {
|
|
430
|
+
readonly title: "CapabilityScope";
|
|
431
|
+
readonly description: "An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.";
|
|
432
|
+
readonly oneOf: readonly [{
|
|
433
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
434
|
+
}, {
|
|
435
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
436
|
+
}, {
|
|
437
|
+
readonly $ref: "#/$defs/CapabilityScopeListed";
|
|
438
|
+
}];
|
|
439
|
+
};
|
|
440
|
+
readonly CapabilityScopeListed: {
|
|
441
|
+
readonly title: "CapabilityScopeListed";
|
|
442
|
+
readonly description: "Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.";
|
|
443
|
+
readonly type: "object";
|
|
444
|
+
readonly additionalProperties: false;
|
|
445
|
+
readonly required: readonly ["scope", "grants"];
|
|
446
|
+
readonly properties: {
|
|
447
|
+
readonly scope: {
|
|
448
|
+
readonly const: "listed";
|
|
449
|
+
};
|
|
450
|
+
readonly grants: {
|
|
451
|
+
readonly type: "array";
|
|
452
|
+
readonly minItems: 1;
|
|
453
|
+
readonly items: {
|
|
454
|
+
readonly $ref: "#/$defs/CapabilityGrant";
|
|
455
|
+
};
|
|
456
|
+
readonly description: "Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).";
|
|
457
|
+
};
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
readonly CapabilityGrant: {
|
|
461
|
+
readonly title: "CapabilityGrant";
|
|
462
|
+
readonly description: "A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.";
|
|
463
|
+
readonly type: "object";
|
|
464
|
+
readonly additionalProperties: false;
|
|
465
|
+
readonly required: readonly ["capability"];
|
|
466
|
+
readonly properties: {
|
|
467
|
+
readonly capability: {
|
|
468
|
+
readonly $ref: "#/$defs/Capability";
|
|
469
|
+
};
|
|
470
|
+
readonly resource: {
|
|
471
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
472
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
473
|
+
};
|
|
474
|
+
readonly additive: {
|
|
475
|
+
readonly type: "boolean";
|
|
476
|
+
readonly description: "`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.";
|
|
477
|
+
};
|
|
478
|
+
};
|
|
479
|
+
};
|
|
480
|
+
readonly AuthorityScope: {
|
|
481
|
+
readonly title: "AuthorityScope";
|
|
482
|
+
readonly description: "An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.";
|
|
483
|
+
readonly oneOf: readonly [{
|
|
484
|
+
readonly $ref: "#/$defs/AuthorityScopeAll";
|
|
485
|
+
}, {
|
|
486
|
+
readonly $ref: "#/$defs/AuthorityScopeNone";
|
|
487
|
+
}, {
|
|
488
|
+
readonly $ref: "#/$defs/AuthorityScopeContexts";
|
|
489
|
+
}];
|
|
490
|
+
};
|
|
491
|
+
readonly AuthorityScopeContexts: {
|
|
492
|
+
readonly title: "AuthorityScopeContexts";
|
|
493
|
+
readonly description: "The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.";
|
|
494
|
+
readonly type: "object";
|
|
495
|
+
readonly additionalProperties: false;
|
|
496
|
+
readonly required: readonly ["scope", "contexts"];
|
|
497
|
+
readonly properties: {
|
|
498
|
+
readonly scope: {
|
|
499
|
+
readonly const: "contexts";
|
|
500
|
+
};
|
|
501
|
+
readonly contexts: {
|
|
502
|
+
readonly type: "array";
|
|
503
|
+
readonly minItems: 1;
|
|
504
|
+
readonly uniqueItems: true;
|
|
505
|
+
readonly items: {
|
|
506
|
+
readonly $ref: "#/$defs/ContextPath";
|
|
507
|
+
};
|
|
508
|
+
readonly description: "Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).";
|
|
509
|
+
};
|
|
510
|
+
};
|
|
511
|
+
};
|
|
512
|
+
readonly ContextPath: {
|
|
513
|
+
readonly title: "ContextPath";
|
|
514
|
+
readonly description: "Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.";
|
|
515
|
+
readonly type: "string";
|
|
516
|
+
readonly minLength: 1;
|
|
517
|
+
readonly maxLength: 512;
|
|
518
|
+
};
|
|
519
|
+
readonly AuthorityScopeNone: {
|
|
520
|
+
readonly title: "AuthorityScopeNone";
|
|
521
|
+
readonly description: "No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.";
|
|
522
|
+
readonly type: "object";
|
|
523
|
+
readonly additionalProperties: false;
|
|
524
|
+
readonly required: readonly ["scope"];
|
|
525
|
+
readonly properties: {
|
|
526
|
+
readonly scope: {
|
|
527
|
+
readonly const: "none";
|
|
528
|
+
};
|
|
529
|
+
};
|
|
530
|
+
};
|
|
531
|
+
readonly AuthorityScopeAll: {
|
|
532
|
+
readonly title: "AuthorityScopeAll";
|
|
533
|
+
readonly description: "Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).";
|
|
534
|
+
readonly type: "object";
|
|
535
|
+
readonly additionalProperties: false;
|
|
536
|
+
readonly required: readonly ["scope"];
|
|
537
|
+
readonly properties: {
|
|
538
|
+
readonly scope: {
|
|
539
|
+
readonly const: "all";
|
|
540
|
+
};
|
|
541
|
+
};
|
|
542
|
+
};
|
|
543
|
+
};
|
|
544
|
+
};
|
|
545
|
+
/** As {@link PAYLOAD_SCHEMA}, for the success-response variant. */
|
|
546
|
+
export declare const RESPONSE_PAYLOAD_SCHEMA: {
|
|
547
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
548
|
+
readonly $ref: "#/$defs/Response";
|
|
549
|
+
readonly $defs: {
|
|
550
|
+
readonly Response: {
|
|
551
|
+
readonly $anchor: "response";
|
|
552
|
+
readonly title: "ACL Update 0.2 — response payload";
|
|
553
|
+
readonly description: "The success response to an acl/update/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/update/0.2#response.";
|
|
554
|
+
readonly type: "object";
|
|
555
|
+
readonly additionalProperties: false;
|
|
556
|
+
readonly required: readonly ["entry"];
|
|
557
|
+
readonly properties: {
|
|
558
|
+
readonly entry: {
|
|
559
|
+
readonly $ref: "#/$defs/AclEntry";
|
|
560
|
+
readonly description: "The realized entry the maintainer now holds, after the amendment.";
|
|
561
|
+
};
|
|
562
|
+
readonly ext: {
|
|
563
|
+
readonly $ref: "#/$defs/Ext";
|
|
564
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
565
|
+
};
|
|
566
|
+
};
|
|
567
|
+
};
|
|
568
|
+
readonly Ext: {
|
|
569
|
+
readonly title: "Ext";
|
|
570
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
571
|
+
readonly type: "object";
|
|
572
|
+
readonly minProperties: 1;
|
|
573
|
+
readonly additionalProperties: true;
|
|
574
|
+
readonly propertyNames: {
|
|
575
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
576
|
+
};
|
|
577
|
+
};
|
|
578
|
+
readonly AclEntry: {
|
|
579
|
+
readonly title: "AclEntry";
|
|
580
|
+
readonly description: "One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).\n\nThe act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer \"may this subject do X\"; `approve` + `approveCapabilities` answer \"may this subject ratify someone else doing X\". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.";
|
|
581
|
+
readonly type: "object";
|
|
582
|
+
readonly additionalProperties: false;
|
|
583
|
+
readonly required: readonly ["subject", "role", "act", "keys", "capabilities"];
|
|
584
|
+
readonly properties: {
|
|
585
|
+
readonly subject: {
|
|
586
|
+
readonly type: "string";
|
|
587
|
+
readonly minLength: 1;
|
|
588
|
+
readonly description: "VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.";
|
|
589
|
+
};
|
|
590
|
+
readonly role: {
|
|
591
|
+
readonly type: "string";
|
|
592
|
+
readonly minLength: 1;
|
|
593
|
+
readonly description: "Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.";
|
|
594
|
+
};
|
|
595
|
+
readonly act: {
|
|
596
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
597
|
+
readonly description: "REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{\"scope\": \"all\"}` (unrestricted — every context the maintainer has), `{\"scope\": \"none\"}` (may act nowhere), or `{\"scope\": \"contexts\", \"contexts\": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.";
|
|
598
|
+
};
|
|
599
|
+
readonly approve: {
|
|
600
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
601
|
+
readonly description: "OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{\"scope\": \"none\"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.";
|
|
602
|
+
};
|
|
603
|
+
readonly capabilities: {
|
|
604
|
+
readonly $ref: "#/$defs/CapabilityScope";
|
|
605
|
+
readonly description: "REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{\"scope\": \"ceiling\"}` (the role's full ceiling, unnarrowed), `{\"scope\": \"none\"}` (no capabilities), or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.";
|
|
606
|
+
};
|
|
607
|
+
readonly approveCapabilities: {
|
|
608
|
+
readonly $ref: "#/$defs/ApproveCapabilityScope";
|
|
609
|
+
readonly description: "OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{\"scope\": \"ceiling\"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{\"scope\": \"none\"}`, or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{\"scope\": \"none\"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.";
|
|
610
|
+
};
|
|
611
|
+
readonly delegatedBy: {
|
|
612
|
+
readonly type: "string";
|
|
613
|
+
readonly minLength: 1;
|
|
614
|
+
readonly description: "VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).";
|
|
615
|
+
};
|
|
616
|
+
readonly keys: {
|
|
617
|
+
readonly $ref: "#/$defs/KeyScope";
|
|
618
|
+
readonly description: "REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{\"scope\": \"all\"}` (every key the entry's act scope reaches), `{\"scope\": \"none\"}` (no keys), or `{\"scope\": \"listed\", \"keys\": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{\"scope\": \"none\"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.";
|
|
619
|
+
};
|
|
620
|
+
readonly label: {
|
|
621
|
+
readonly type: "string";
|
|
622
|
+
readonly maxLength: 256;
|
|
623
|
+
readonly description: "Optional human-readable label. Confers nothing.";
|
|
624
|
+
};
|
|
625
|
+
readonly createdAt: {
|
|
626
|
+
readonly type: "string";
|
|
627
|
+
readonly format: "date-time";
|
|
628
|
+
};
|
|
629
|
+
readonly createdBy: {
|
|
630
|
+
readonly type: "string";
|
|
631
|
+
readonly description: "VID of the party that originally wrote this entry.";
|
|
632
|
+
};
|
|
633
|
+
readonly updatedAt: {
|
|
634
|
+
readonly type: "string";
|
|
635
|
+
readonly format: "date-time";
|
|
636
|
+
};
|
|
637
|
+
readonly updatedBy: {
|
|
638
|
+
readonly type: "string";
|
|
639
|
+
readonly description: "VID of the party that last modified this entry.";
|
|
640
|
+
};
|
|
641
|
+
readonly expiresAt: {
|
|
642
|
+
readonly type: "string";
|
|
643
|
+
readonly format: "date-time";
|
|
644
|
+
readonly description: "Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.";
|
|
645
|
+
};
|
|
646
|
+
readonly stepUp: {
|
|
647
|
+
readonly type: "object";
|
|
648
|
+
readonly additionalProperties: false;
|
|
649
|
+
readonly description: "Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.";
|
|
650
|
+
readonly properties: {
|
|
651
|
+
readonly approver: {
|
|
652
|
+
readonly type: "string";
|
|
653
|
+
readonly description: "VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.";
|
|
654
|
+
};
|
|
655
|
+
readonly require: {
|
|
656
|
+
readonly type: "string";
|
|
657
|
+
readonly enum: readonly ["self", "delegated"];
|
|
658
|
+
readonly description: "Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).";
|
|
659
|
+
};
|
|
660
|
+
};
|
|
661
|
+
};
|
|
662
|
+
readonly ext: {
|
|
663
|
+
readonly $ref: "#/$defs/Ext";
|
|
664
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.";
|
|
665
|
+
};
|
|
666
|
+
};
|
|
667
|
+
};
|
|
668
|
+
readonly KeyScope: {
|
|
669
|
+
readonly title: "KeyScope";
|
|
670
|
+
readonly description: "An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.";
|
|
671
|
+
readonly oneOf: readonly [{
|
|
672
|
+
readonly $ref: "#/$defs/KeyScopeAll";
|
|
673
|
+
}, {
|
|
674
|
+
readonly $ref: "#/$defs/KeyScopeNone";
|
|
675
|
+
}, {
|
|
676
|
+
readonly $ref: "#/$defs/KeyScopeListed";
|
|
677
|
+
}];
|
|
678
|
+
};
|
|
679
|
+
readonly KeyScopeListed: {
|
|
680
|
+
readonly title: "KeyScopeListed";
|
|
681
|
+
readonly description: "Exactly the listed keys, intersected with the entry's act scope.";
|
|
682
|
+
readonly type: "object";
|
|
683
|
+
readonly additionalProperties: false;
|
|
684
|
+
readonly required: readonly ["scope", "keys"];
|
|
685
|
+
readonly properties: {
|
|
686
|
+
readonly scope: {
|
|
687
|
+
readonly const: "listed";
|
|
688
|
+
};
|
|
689
|
+
readonly keys: {
|
|
690
|
+
readonly type: "array";
|
|
691
|
+
readonly minItems: 1;
|
|
692
|
+
readonly uniqueItems: true;
|
|
693
|
+
readonly items: {
|
|
694
|
+
readonly type: "string";
|
|
695
|
+
readonly minLength: 1;
|
|
696
|
+
readonly maxLength: 512;
|
|
697
|
+
};
|
|
698
|
+
readonly description: "Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).";
|
|
699
|
+
};
|
|
700
|
+
};
|
|
701
|
+
};
|
|
702
|
+
readonly KeyScopeNone: {
|
|
703
|
+
readonly title: "KeyScopeNone";
|
|
704
|
+
readonly description: "No keys.";
|
|
705
|
+
readonly type: "object";
|
|
706
|
+
readonly additionalProperties: false;
|
|
707
|
+
readonly required: readonly ["scope"];
|
|
708
|
+
readonly properties: {
|
|
709
|
+
readonly scope: {
|
|
710
|
+
readonly const: "none";
|
|
711
|
+
};
|
|
712
|
+
};
|
|
713
|
+
};
|
|
714
|
+
readonly KeyScopeAll: {
|
|
715
|
+
readonly title: "KeyScopeAll";
|
|
716
|
+
readonly description: "Every key the entry's act scope reaches.";
|
|
717
|
+
readonly type: "object";
|
|
718
|
+
readonly additionalProperties: false;
|
|
719
|
+
readonly required: readonly ["scope"];
|
|
720
|
+
readonly properties: {
|
|
721
|
+
readonly scope: {
|
|
722
|
+
readonly const: "all";
|
|
723
|
+
};
|
|
724
|
+
};
|
|
725
|
+
};
|
|
726
|
+
readonly ApproveCapabilityScope: {
|
|
727
|
+
readonly title: "ApproveCapabilityScope";
|
|
728
|
+
readonly description: "An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.";
|
|
729
|
+
readonly oneOf: readonly [{
|
|
730
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
731
|
+
}, {
|
|
732
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
733
|
+
}, {
|
|
734
|
+
readonly $ref: "#/$defs/ApproveCapabilityScopeListed";
|
|
735
|
+
}];
|
|
736
|
+
};
|
|
737
|
+
readonly ApproveCapabilityScopeListed: {
|
|
738
|
+
readonly title: "ApproveCapabilityScopeListed";
|
|
739
|
+
readonly description: "Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.";
|
|
740
|
+
readonly type: "object";
|
|
741
|
+
readonly additionalProperties: false;
|
|
742
|
+
readonly required: readonly ["scope", "grants"];
|
|
743
|
+
readonly properties: {
|
|
744
|
+
readonly scope: {
|
|
745
|
+
readonly const: "listed";
|
|
746
|
+
};
|
|
747
|
+
readonly grants: {
|
|
748
|
+
readonly type: "array";
|
|
749
|
+
readonly minItems: 1;
|
|
750
|
+
readonly items: {
|
|
751
|
+
readonly $ref: "#/$defs/CapabilityRef";
|
|
752
|
+
};
|
|
753
|
+
readonly description: "Non-empty list of approvable capabilities. An empty array is invalid.";
|
|
754
|
+
};
|
|
755
|
+
};
|
|
756
|
+
};
|
|
757
|
+
readonly CapabilityRef: {
|
|
758
|
+
readonly title: "CapabilityRef";
|
|
759
|
+
readonly description: "A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.";
|
|
760
|
+
readonly type: "object";
|
|
761
|
+
readonly additionalProperties: false;
|
|
762
|
+
readonly required: readonly ["capability"];
|
|
763
|
+
readonly properties: {
|
|
764
|
+
readonly capability: {
|
|
765
|
+
readonly $ref: "#/$defs/Capability";
|
|
766
|
+
};
|
|
767
|
+
readonly resource: {
|
|
768
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
769
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
770
|
+
};
|
|
771
|
+
};
|
|
772
|
+
};
|
|
773
|
+
readonly ResourceQualifier: {
|
|
774
|
+
readonly title: "ResourceQualifier";
|
|
775
|
+
readonly description: "Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.";
|
|
776
|
+
readonly type: "string";
|
|
777
|
+
readonly minLength: 1;
|
|
778
|
+
readonly maxLength: 512;
|
|
779
|
+
};
|
|
780
|
+
readonly Capability: {
|
|
781
|
+
readonly title: "Capability";
|
|
782
|
+
readonly description: "Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.";
|
|
783
|
+
readonly type: "string";
|
|
784
|
+
readonly minLength: 1;
|
|
785
|
+
readonly maxLength: 128;
|
|
786
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)*$";
|
|
787
|
+
};
|
|
788
|
+
readonly CapabilityScopeNone: {
|
|
789
|
+
readonly title: "CapabilityScopeNone";
|
|
790
|
+
readonly description: "No capabilities on this axis.";
|
|
791
|
+
readonly type: "object";
|
|
792
|
+
readonly additionalProperties: false;
|
|
793
|
+
readonly required: readonly ["scope"];
|
|
794
|
+
readonly properties: {
|
|
795
|
+
readonly scope: {
|
|
796
|
+
readonly const: "none";
|
|
797
|
+
};
|
|
798
|
+
};
|
|
799
|
+
};
|
|
800
|
+
readonly CapabilityScopeCeiling: {
|
|
801
|
+
readonly title: "CapabilityScopeCeiling";
|
|
802
|
+
readonly description: "The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of \"no narrowing\".";
|
|
803
|
+
readonly type: "object";
|
|
804
|
+
readonly additionalProperties: false;
|
|
805
|
+
readonly required: readonly ["scope"];
|
|
806
|
+
readonly properties: {
|
|
807
|
+
readonly scope: {
|
|
808
|
+
readonly const: "ceiling";
|
|
809
|
+
};
|
|
810
|
+
};
|
|
811
|
+
};
|
|
812
|
+
readonly CapabilityScope: {
|
|
813
|
+
readonly title: "CapabilityScope";
|
|
814
|
+
readonly description: "An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.";
|
|
815
|
+
readonly oneOf: readonly [{
|
|
816
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
817
|
+
}, {
|
|
818
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
819
|
+
}, {
|
|
820
|
+
readonly $ref: "#/$defs/CapabilityScopeListed";
|
|
821
|
+
}];
|
|
822
|
+
};
|
|
823
|
+
readonly CapabilityScopeListed: {
|
|
824
|
+
readonly title: "CapabilityScopeListed";
|
|
825
|
+
readonly description: "Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.";
|
|
826
|
+
readonly type: "object";
|
|
827
|
+
readonly additionalProperties: false;
|
|
828
|
+
readonly required: readonly ["scope", "grants"];
|
|
829
|
+
readonly properties: {
|
|
830
|
+
readonly scope: {
|
|
831
|
+
readonly const: "listed";
|
|
832
|
+
};
|
|
833
|
+
readonly grants: {
|
|
834
|
+
readonly type: "array";
|
|
835
|
+
readonly minItems: 1;
|
|
836
|
+
readonly items: {
|
|
837
|
+
readonly $ref: "#/$defs/CapabilityGrant";
|
|
838
|
+
};
|
|
839
|
+
readonly description: "Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).";
|
|
840
|
+
};
|
|
841
|
+
};
|
|
842
|
+
};
|
|
843
|
+
readonly CapabilityGrant: {
|
|
844
|
+
readonly title: "CapabilityGrant";
|
|
845
|
+
readonly description: "A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.";
|
|
846
|
+
readonly type: "object";
|
|
847
|
+
readonly additionalProperties: false;
|
|
848
|
+
readonly required: readonly ["capability"];
|
|
849
|
+
readonly properties: {
|
|
850
|
+
readonly capability: {
|
|
851
|
+
readonly $ref: "#/$defs/Capability";
|
|
852
|
+
};
|
|
853
|
+
readonly resource: {
|
|
854
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
855
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
856
|
+
};
|
|
857
|
+
readonly additive: {
|
|
858
|
+
readonly type: "boolean";
|
|
859
|
+
readonly description: "`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.";
|
|
860
|
+
};
|
|
861
|
+
};
|
|
862
|
+
};
|
|
863
|
+
readonly AuthorityScope: {
|
|
864
|
+
readonly title: "AuthorityScope";
|
|
865
|
+
readonly description: "An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.";
|
|
866
|
+
readonly oneOf: readonly [{
|
|
867
|
+
readonly $ref: "#/$defs/AuthorityScopeAll";
|
|
868
|
+
}, {
|
|
869
|
+
readonly $ref: "#/$defs/AuthorityScopeNone";
|
|
870
|
+
}, {
|
|
871
|
+
readonly $ref: "#/$defs/AuthorityScopeContexts";
|
|
872
|
+
}];
|
|
873
|
+
};
|
|
874
|
+
readonly AuthorityScopeContexts: {
|
|
875
|
+
readonly title: "AuthorityScopeContexts";
|
|
876
|
+
readonly description: "The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.";
|
|
877
|
+
readonly type: "object";
|
|
878
|
+
readonly additionalProperties: false;
|
|
879
|
+
readonly required: readonly ["scope", "contexts"];
|
|
880
|
+
readonly properties: {
|
|
881
|
+
readonly scope: {
|
|
882
|
+
readonly const: "contexts";
|
|
883
|
+
};
|
|
884
|
+
readonly contexts: {
|
|
885
|
+
readonly type: "array";
|
|
886
|
+
readonly minItems: 1;
|
|
887
|
+
readonly uniqueItems: true;
|
|
888
|
+
readonly items: {
|
|
889
|
+
readonly $ref: "#/$defs/ContextPath";
|
|
890
|
+
};
|
|
891
|
+
readonly description: "Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).";
|
|
892
|
+
};
|
|
893
|
+
};
|
|
894
|
+
};
|
|
895
|
+
readonly ContextPath: {
|
|
896
|
+
readonly title: "ContextPath";
|
|
897
|
+
readonly description: "Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.";
|
|
898
|
+
readonly type: "string";
|
|
899
|
+
readonly minLength: 1;
|
|
900
|
+
readonly maxLength: 512;
|
|
901
|
+
};
|
|
902
|
+
readonly AuthorityScopeNone: {
|
|
903
|
+
readonly title: "AuthorityScopeNone";
|
|
904
|
+
readonly description: "No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.";
|
|
905
|
+
readonly type: "object";
|
|
906
|
+
readonly additionalProperties: false;
|
|
907
|
+
readonly required: readonly ["scope"];
|
|
908
|
+
readonly properties: {
|
|
909
|
+
readonly scope: {
|
|
910
|
+
readonly const: "none";
|
|
911
|
+
};
|
|
912
|
+
};
|
|
913
|
+
};
|
|
914
|
+
readonly AuthorityScopeAll: {
|
|
915
|
+
readonly title: "AuthorityScopeAll";
|
|
916
|
+
readonly description: "Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).";
|
|
917
|
+
readonly type: "object";
|
|
918
|
+
readonly additionalProperties: false;
|
|
919
|
+
readonly required: readonly ["scope"];
|
|
920
|
+
readonly properties: {
|
|
921
|
+
readonly scope: {
|
|
922
|
+
readonly const: "all";
|
|
923
|
+
};
|
|
924
|
+
};
|
|
925
|
+
};
|
|
926
|
+
};
|
|
927
|
+
};
|
|
928
|
+
/**
|
|
929
|
+
* SPEC.md §7.2 policy for the request variant, from this specification's
|
|
930
|
+
* front matter. Pass to `consumeInbound` — items 5b, 7 and 8 are
|
|
931
|
+
* per-specification and cannot be derived from the document alone, and
|
|
932
|
+
* item 2 needs the schema this carries.
|
|
933
|
+
*/
|
|
934
|
+
export declare const SPEC: {
|
|
935
|
+
readonly typeUri: "https://trusttasks.org/spec/acl/update/0.2";
|
|
936
|
+
readonly isBearer: false;
|
|
937
|
+
readonly isProofRequired: true;
|
|
938
|
+
readonly isRecipientRequired: true;
|
|
939
|
+
readonly isIssuedAtRequired: true;
|
|
940
|
+
readonly payloadSchema: {
|
|
941
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
942
|
+
readonly $id: "https://trusttasks.org/spec/acl/update/0.2";
|
|
943
|
+
readonly title: "ACL Update 0.2 — payload";
|
|
944
|
+
readonly description: "Amend the non-role attributes of an existing AclEntry 0.2: its act scope (widening only), approve scope, capability scope, approvable-capability scope, key scope, label, expiry or step-up requirement. Every member REPLACES the stored value; an omitted member leaves it unchanged. Role changes are NOT expressible here — they go through acl/change-role, which requires the current role as a compare-and-swap. `delegatedBy` and the provenance timestamps are maintainer-populated and not settable.";
|
|
945
|
+
readonly type: "object";
|
|
946
|
+
readonly additionalProperties: false;
|
|
947
|
+
readonly required: readonly ["subject"];
|
|
948
|
+
readonly properties: {
|
|
949
|
+
readonly subject: {
|
|
950
|
+
readonly type: "string";
|
|
951
|
+
readonly minLength: 1;
|
|
952
|
+
readonly description: "VID of the entry to amend. The entry MUST already exist; this task does not create one (use acl/grant).";
|
|
953
|
+
};
|
|
954
|
+
readonly act: {
|
|
955
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
956
|
+
readonly description: "Replacement act scope, in the same explicit form as the entry's (`all`, `none`, or a non-empty context list). A replacement that WIDENS or equals the stored scope is accepted, subject to the granter bound. NARROWING THE ACT SCOPE IS A REVOCATION and a consumer MUST refuse it here with `narrowingNotPermitted`, directing the caller to acl/revoke, so that every removal of where a subject may act passes through the task that is audited and reasoned as a revocation.";
|
|
957
|
+
};
|
|
958
|
+
readonly approve: {
|
|
959
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
960
|
+
readonly description: "Replacement approve scope. To withdraw approve authority entirely, send `{\"scope\": \"none\"}` — there is no null form, because the explicit value is the only spelling that cannot be misread. Widening is an escalation vector (a subject able to approve can ratify operations it could not authorize) and is bounded by the granter's own approve authority. Narrowing is accepted here and is a privilege reduction (see the specification).";
|
|
961
|
+
};
|
|
962
|
+
readonly capabilities: {
|
|
963
|
+
readonly $ref: "#/$defs/CapabilityScope";
|
|
964
|
+
readonly description: "Replacement capability scope, applied wholesale, in the same explicit form as the entry's. Omitted leaves it unchanged. `{\"scope\": \"ceiling\"}` returns the entry to its role's full ceiling — a privilege INCREASE, bounded and gated like any widening; `{\"scope\": \"none\"}` removes every capability; `listed` states the exact set. There is no null form. Every listed capability is checked as on a grant (registry, ceiling, additive, granter bound). A replacement that removes a capability the entry held is a privilege reduction.";
|
|
965
|
+
};
|
|
966
|
+
readonly approveCapabilities: {
|
|
967
|
+
readonly $ref: "#/$defs/ApproveCapabilityScope";
|
|
968
|
+
readonly description: "Replacement approvable-capability scope, applied wholesale. Omitted leaves it unchanged. `{\"scope\": \"ceiling\"}` lets the subject approve its role's full approve ceiling within its approve scope (a privilege increase); `{\"scope\": \"none\"}` withdraws it; `listed` states the exact set. There is no null form. Bounded by the granter's own approve authority.";
|
|
969
|
+
};
|
|
970
|
+
readonly keys: {
|
|
971
|
+
readonly $ref: "#/$defs/KeyScope";
|
|
972
|
+
readonly description: "Replacement key scope, applied wholesale. Omitted leaves it unchanged. `{\"scope\": \"all\"}` lets the subject reach every key within its act scope again — a privilege increase a consumer SHOULD gate like clearing `expiresAt`; `{\"scope\": \"none\"}` removes every key; `listed` states the exact set. There is no null form. A replacement that narrows the stored key scope IS a privilege reduction: it is accepted here, because acl/revoke/0.2 narrows only the act scope, but the consumer MUST audit it as a reduction and apply it at the subject's next authorization decision.";
|
|
973
|
+
};
|
|
974
|
+
readonly label: {
|
|
975
|
+
readonly type: readonly ["string", "null"];
|
|
976
|
+
readonly maxLength: 256;
|
|
977
|
+
readonly description: "Replacement human-readable label. Explicit `null` clears it. Omitted leaves it unchanged.";
|
|
978
|
+
};
|
|
979
|
+
readonly expiresAt: {
|
|
980
|
+
readonly type: readonly ["string", "null"];
|
|
981
|
+
readonly format: "date-time";
|
|
982
|
+
readonly description: "Replacement expiry. Explicit `null` makes the entry permanent — a privilege increase, which a consumer SHOULD gate at least as strictly as the original grant, and which is refused where the granter's own entry expires.";
|
|
983
|
+
};
|
|
984
|
+
readonly stepUp: {
|
|
985
|
+
readonly type: "object";
|
|
986
|
+
readonly additionalProperties: false;
|
|
987
|
+
readonly description: "Replacement per-entry step-up configuration. Same additive-only rule as on the entry itself: it MAY raise the assurance required of this subject above the system floor but MUST NOT lower it.";
|
|
988
|
+
readonly properties: {
|
|
989
|
+
readonly approver: {
|
|
990
|
+
readonly type: readonly ["string", "null"];
|
|
991
|
+
readonly description: "VID that ratifies step-up for this subject. `null` clears it.";
|
|
992
|
+
};
|
|
993
|
+
readonly require: {
|
|
994
|
+
readonly type: readonly ["string", "null"];
|
|
995
|
+
readonly enum: readonly ["self", "delegated", null];
|
|
996
|
+
readonly description: "Minimum step-up mode. `null` clears the per-entry override.";
|
|
997
|
+
};
|
|
998
|
+
};
|
|
999
|
+
};
|
|
1000
|
+
readonly reason: {
|
|
1001
|
+
readonly type: "string";
|
|
1002
|
+
readonly maxLength: 1024;
|
|
1003
|
+
readonly description: "Optional human-readable rationale, recorded with the change.";
|
|
1004
|
+
};
|
|
1005
|
+
readonly ext: {
|
|
1006
|
+
readonly $ref: "#/$defs/Ext";
|
|
1007
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
1008
|
+
};
|
|
1009
|
+
};
|
|
1010
|
+
readonly $defs: {
|
|
1011
|
+
readonly Response: {
|
|
1012
|
+
readonly $anchor: "response";
|
|
1013
|
+
readonly title: "ACL Update 0.2 — response payload";
|
|
1014
|
+
readonly description: "The success response to an acl/update/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/update/0.2#response.";
|
|
1015
|
+
readonly type: "object";
|
|
1016
|
+
readonly additionalProperties: false;
|
|
1017
|
+
readonly required: readonly ["entry"];
|
|
1018
|
+
readonly properties: {
|
|
1019
|
+
readonly entry: {
|
|
1020
|
+
readonly $ref: "#/$defs/AclEntry";
|
|
1021
|
+
readonly description: "The realized entry the maintainer now holds, after the amendment.";
|
|
1022
|
+
};
|
|
1023
|
+
readonly ext: {
|
|
1024
|
+
readonly $ref: "#/$defs/Ext";
|
|
1025
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
1026
|
+
};
|
|
1027
|
+
};
|
|
1028
|
+
};
|
|
1029
|
+
readonly Ext: {
|
|
1030
|
+
readonly title: "Ext";
|
|
1031
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
1032
|
+
readonly type: "object";
|
|
1033
|
+
readonly minProperties: 1;
|
|
1034
|
+
readonly additionalProperties: true;
|
|
1035
|
+
readonly propertyNames: {
|
|
1036
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
1037
|
+
};
|
|
1038
|
+
};
|
|
1039
|
+
readonly AclEntry: {
|
|
1040
|
+
readonly title: "AclEntry";
|
|
1041
|
+
readonly description: "One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).\n\nThe act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer \"may this subject do X\"; `approve` + `approveCapabilities` answer \"may this subject ratify someone else doing X\". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.";
|
|
1042
|
+
readonly type: "object";
|
|
1043
|
+
readonly additionalProperties: false;
|
|
1044
|
+
readonly required: readonly ["subject", "role", "act", "keys", "capabilities"];
|
|
1045
|
+
readonly properties: {
|
|
1046
|
+
readonly subject: {
|
|
1047
|
+
readonly type: "string";
|
|
1048
|
+
readonly minLength: 1;
|
|
1049
|
+
readonly description: "VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.";
|
|
1050
|
+
};
|
|
1051
|
+
readonly role: {
|
|
1052
|
+
readonly type: "string";
|
|
1053
|
+
readonly minLength: 1;
|
|
1054
|
+
readonly description: "Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.";
|
|
1055
|
+
};
|
|
1056
|
+
readonly act: {
|
|
1057
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
1058
|
+
readonly description: "REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{\"scope\": \"all\"}` (unrestricted — every context the maintainer has), `{\"scope\": \"none\"}` (may act nowhere), or `{\"scope\": \"contexts\", \"contexts\": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.";
|
|
1059
|
+
};
|
|
1060
|
+
readonly approve: {
|
|
1061
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
1062
|
+
readonly description: "OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{\"scope\": \"none\"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.";
|
|
1063
|
+
};
|
|
1064
|
+
readonly capabilities: {
|
|
1065
|
+
readonly $ref: "#/$defs/CapabilityScope";
|
|
1066
|
+
readonly description: "REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{\"scope\": \"ceiling\"}` (the role's full ceiling, unnarrowed), `{\"scope\": \"none\"}` (no capabilities), or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.";
|
|
1067
|
+
};
|
|
1068
|
+
readonly approveCapabilities: {
|
|
1069
|
+
readonly $ref: "#/$defs/ApproveCapabilityScope";
|
|
1070
|
+
readonly description: "OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{\"scope\": \"ceiling\"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{\"scope\": \"none\"}`, or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{\"scope\": \"none\"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.";
|
|
1071
|
+
};
|
|
1072
|
+
readonly delegatedBy: {
|
|
1073
|
+
readonly type: "string";
|
|
1074
|
+
readonly minLength: 1;
|
|
1075
|
+
readonly description: "VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).";
|
|
1076
|
+
};
|
|
1077
|
+
readonly keys: {
|
|
1078
|
+
readonly $ref: "#/$defs/KeyScope";
|
|
1079
|
+
readonly description: "REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{\"scope\": \"all\"}` (every key the entry's act scope reaches), `{\"scope\": \"none\"}` (no keys), or `{\"scope\": \"listed\", \"keys\": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{\"scope\": \"none\"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.";
|
|
1080
|
+
};
|
|
1081
|
+
readonly label: {
|
|
1082
|
+
readonly type: "string";
|
|
1083
|
+
readonly maxLength: 256;
|
|
1084
|
+
readonly description: "Optional human-readable label. Confers nothing.";
|
|
1085
|
+
};
|
|
1086
|
+
readonly createdAt: {
|
|
1087
|
+
readonly type: "string";
|
|
1088
|
+
readonly format: "date-time";
|
|
1089
|
+
};
|
|
1090
|
+
readonly createdBy: {
|
|
1091
|
+
readonly type: "string";
|
|
1092
|
+
readonly description: "VID of the party that originally wrote this entry.";
|
|
1093
|
+
};
|
|
1094
|
+
readonly updatedAt: {
|
|
1095
|
+
readonly type: "string";
|
|
1096
|
+
readonly format: "date-time";
|
|
1097
|
+
};
|
|
1098
|
+
readonly updatedBy: {
|
|
1099
|
+
readonly type: "string";
|
|
1100
|
+
readonly description: "VID of the party that last modified this entry.";
|
|
1101
|
+
};
|
|
1102
|
+
readonly expiresAt: {
|
|
1103
|
+
readonly type: "string";
|
|
1104
|
+
readonly format: "date-time";
|
|
1105
|
+
readonly description: "Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.";
|
|
1106
|
+
};
|
|
1107
|
+
readonly stepUp: {
|
|
1108
|
+
readonly type: "object";
|
|
1109
|
+
readonly additionalProperties: false;
|
|
1110
|
+
readonly description: "Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.";
|
|
1111
|
+
readonly properties: {
|
|
1112
|
+
readonly approver: {
|
|
1113
|
+
readonly type: "string";
|
|
1114
|
+
readonly description: "VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.";
|
|
1115
|
+
};
|
|
1116
|
+
readonly require: {
|
|
1117
|
+
readonly type: "string";
|
|
1118
|
+
readonly enum: readonly ["self", "delegated"];
|
|
1119
|
+
readonly description: "Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).";
|
|
1120
|
+
};
|
|
1121
|
+
};
|
|
1122
|
+
};
|
|
1123
|
+
readonly ext: {
|
|
1124
|
+
readonly $ref: "#/$defs/Ext";
|
|
1125
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.";
|
|
1126
|
+
};
|
|
1127
|
+
};
|
|
1128
|
+
};
|
|
1129
|
+
readonly KeyScope: {
|
|
1130
|
+
readonly title: "KeyScope";
|
|
1131
|
+
readonly description: "An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.";
|
|
1132
|
+
readonly oneOf: readonly [{
|
|
1133
|
+
readonly $ref: "#/$defs/KeyScopeAll";
|
|
1134
|
+
}, {
|
|
1135
|
+
readonly $ref: "#/$defs/KeyScopeNone";
|
|
1136
|
+
}, {
|
|
1137
|
+
readonly $ref: "#/$defs/KeyScopeListed";
|
|
1138
|
+
}];
|
|
1139
|
+
};
|
|
1140
|
+
readonly KeyScopeListed: {
|
|
1141
|
+
readonly title: "KeyScopeListed";
|
|
1142
|
+
readonly description: "Exactly the listed keys, intersected with the entry's act scope.";
|
|
1143
|
+
readonly type: "object";
|
|
1144
|
+
readonly additionalProperties: false;
|
|
1145
|
+
readonly required: readonly ["scope", "keys"];
|
|
1146
|
+
readonly properties: {
|
|
1147
|
+
readonly scope: {
|
|
1148
|
+
readonly const: "listed";
|
|
1149
|
+
};
|
|
1150
|
+
readonly keys: {
|
|
1151
|
+
readonly type: "array";
|
|
1152
|
+
readonly minItems: 1;
|
|
1153
|
+
readonly uniqueItems: true;
|
|
1154
|
+
readonly items: {
|
|
1155
|
+
readonly type: "string";
|
|
1156
|
+
readonly minLength: 1;
|
|
1157
|
+
readonly maxLength: 512;
|
|
1158
|
+
};
|
|
1159
|
+
readonly description: "Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).";
|
|
1160
|
+
};
|
|
1161
|
+
};
|
|
1162
|
+
};
|
|
1163
|
+
readonly KeyScopeNone: {
|
|
1164
|
+
readonly title: "KeyScopeNone";
|
|
1165
|
+
readonly description: "No keys.";
|
|
1166
|
+
readonly type: "object";
|
|
1167
|
+
readonly additionalProperties: false;
|
|
1168
|
+
readonly required: readonly ["scope"];
|
|
1169
|
+
readonly properties: {
|
|
1170
|
+
readonly scope: {
|
|
1171
|
+
readonly const: "none";
|
|
1172
|
+
};
|
|
1173
|
+
};
|
|
1174
|
+
};
|
|
1175
|
+
readonly KeyScopeAll: {
|
|
1176
|
+
readonly title: "KeyScopeAll";
|
|
1177
|
+
readonly description: "Every key the entry's act scope reaches.";
|
|
1178
|
+
readonly type: "object";
|
|
1179
|
+
readonly additionalProperties: false;
|
|
1180
|
+
readonly required: readonly ["scope"];
|
|
1181
|
+
readonly properties: {
|
|
1182
|
+
readonly scope: {
|
|
1183
|
+
readonly const: "all";
|
|
1184
|
+
};
|
|
1185
|
+
};
|
|
1186
|
+
};
|
|
1187
|
+
readonly ApproveCapabilityScope: {
|
|
1188
|
+
readonly title: "ApproveCapabilityScope";
|
|
1189
|
+
readonly description: "An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.";
|
|
1190
|
+
readonly oneOf: readonly [{
|
|
1191
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
1192
|
+
}, {
|
|
1193
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
1194
|
+
}, {
|
|
1195
|
+
readonly $ref: "#/$defs/ApproveCapabilityScopeListed";
|
|
1196
|
+
}];
|
|
1197
|
+
};
|
|
1198
|
+
readonly ApproveCapabilityScopeListed: {
|
|
1199
|
+
readonly title: "ApproveCapabilityScopeListed";
|
|
1200
|
+
readonly description: "Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.";
|
|
1201
|
+
readonly type: "object";
|
|
1202
|
+
readonly additionalProperties: false;
|
|
1203
|
+
readonly required: readonly ["scope", "grants"];
|
|
1204
|
+
readonly properties: {
|
|
1205
|
+
readonly scope: {
|
|
1206
|
+
readonly const: "listed";
|
|
1207
|
+
};
|
|
1208
|
+
readonly grants: {
|
|
1209
|
+
readonly type: "array";
|
|
1210
|
+
readonly minItems: 1;
|
|
1211
|
+
readonly items: {
|
|
1212
|
+
readonly $ref: "#/$defs/CapabilityRef";
|
|
1213
|
+
};
|
|
1214
|
+
readonly description: "Non-empty list of approvable capabilities. An empty array is invalid.";
|
|
1215
|
+
};
|
|
1216
|
+
};
|
|
1217
|
+
};
|
|
1218
|
+
readonly CapabilityRef: {
|
|
1219
|
+
readonly title: "CapabilityRef";
|
|
1220
|
+
readonly description: "A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.";
|
|
1221
|
+
readonly type: "object";
|
|
1222
|
+
readonly additionalProperties: false;
|
|
1223
|
+
readonly required: readonly ["capability"];
|
|
1224
|
+
readonly properties: {
|
|
1225
|
+
readonly capability: {
|
|
1226
|
+
readonly $ref: "#/$defs/Capability";
|
|
1227
|
+
};
|
|
1228
|
+
readonly resource: {
|
|
1229
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
1230
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
1231
|
+
};
|
|
1232
|
+
};
|
|
1233
|
+
};
|
|
1234
|
+
readonly ResourceQualifier: {
|
|
1235
|
+
readonly title: "ResourceQualifier";
|
|
1236
|
+
readonly description: "Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.";
|
|
1237
|
+
readonly type: "string";
|
|
1238
|
+
readonly minLength: 1;
|
|
1239
|
+
readonly maxLength: 512;
|
|
1240
|
+
};
|
|
1241
|
+
readonly Capability: {
|
|
1242
|
+
readonly title: "Capability";
|
|
1243
|
+
readonly description: "Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.";
|
|
1244
|
+
readonly type: "string";
|
|
1245
|
+
readonly minLength: 1;
|
|
1246
|
+
readonly maxLength: 128;
|
|
1247
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)*$";
|
|
1248
|
+
};
|
|
1249
|
+
readonly CapabilityScopeNone: {
|
|
1250
|
+
readonly title: "CapabilityScopeNone";
|
|
1251
|
+
readonly description: "No capabilities on this axis.";
|
|
1252
|
+
readonly type: "object";
|
|
1253
|
+
readonly additionalProperties: false;
|
|
1254
|
+
readonly required: readonly ["scope"];
|
|
1255
|
+
readonly properties: {
|
|
1256
|
+
readonly scope: {
|
|
1257
|
+
readonly const: "none";
|
|
1258
|
+
};
|
|
1259
|
+
};
|
|
1260
|
+
};
|
|
1261
|
+
readonly CapabilityScopeCeiling: {
|
|
1262
|
+
readonly title: "CapabilityScopeCeiling";
|
|
1263
|
+
readonly description: "The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of \"no narrowing\".";
|
|
1264
|
+
readonly type: "object";
|
|
1265
|
+
readonly additionalProperties: false;
|
|
1266
|
+
readonly required: readonly ["scope"];
|
|
1267
|
+
readonly properties: {
|
|
1268
|
+
readonly scope: {
|
|
1269
|
+
readonly const: "ceiling";
|
|
1270
|
+
};
|
|
1271
|
+
};
|
|
1272
|
+
};
|
|
1273
|
+
readonly CapabilityScope: {
|
|
1274
|
+
readonly title: "CapabilityScope";
|
|
1275
|
+
readonly description: "An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.";
|
|
1276
|
+
readonly oneOf: readonly [{
|
|
1277
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
1278
|
+
}, {
|
|
1279
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
1280
|
+
}, {
|
|
1281
|
+
readonly $ref: "#/$defs/CapabilityScopeListed";
|
|
1282
|
+
}];
|
|
1283
|
+
};
|
|
1284
|
+
readonly CapabilityScopeListed: {
|
|
1285
|
+
readonly title: "CapabilityScopeListed";
|
|
1286
|
+
readonly description: "Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.";
|
|
1287
|
+
readonly type: "object";
|
|
1288
|
+
readonly additionalProperties: false;
|
|
1289
|
+
readonly required: readonly ["scope", "grants"];
|
|
1290
|
+
readonly properties: {
|
|
1291
|
+
readonly scope: {
|
|
1292
|
+
readonly const: "listed";
|
|
1293
|
+
};
|
|
1294
|
+
readonly grants: {
|
|
1295
|
+
readonly type: "array";
|
|
1296
|
+
readonly minItems: 1;
|
|
1297
|
+
readonly items: {
|
|
1298
|
+
readonly $ref: "#/$defs/CapabilityGrant";
|
|
1299
|
+
};
|
|
1300
|
+
readonly description: "Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).";
|
|
1301
|
+
};
|
|
1302
|
+
};
|
|
1303
|
+
};
|
|
1304
|
+
readonly CapabilityGrant: {
|
|
1305
|
+
readonly title: "CapabilityGrant";
|
|
1306
|
+
readonly description: "A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.";
|
|
1307
|
+
readonly type: "object";
|
|
1308
|
+
readonly additionalProperties: false;
|
|
1309
|
+
readonly required: readonly ["capability"];
|
|
1310
|
+
readonly properties: {
|
|
1311
|
+
readonly capability: {
|
|
1312
|
+
readonly $ref: "#/$defs/Capability";
|
|
1313
|
+
};
|
|
1314
|
+
readonly resource: {
|
|
1315
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
1316
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
1317
|
+
};
|
|
1318
|
+
readonly additive: {
|
|
1319
|
+
readonly type: "boolean";
|
|
1320
|
+
readonly description: "`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.";
|
|
1321
|
+
};
|
|
1322
|
+
};
|
|
1323
|
+
};
|
|
1324
|
+
readonly AuthorityScope: {
|
|
1325
|
+
readonly title: "AuthorityScope";
|
|
1326
|
+
readonly description: "An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.";
|
|
1327
|
+
readonly oneOf: readonly [{
|
|
1328
|
+
readonly $ref: "#/$defs/AuthorityScopeAll";
|
|
1329
|
+
}, {
|
|
1330
|
+
readonly $ref: "#/$defs/AuthorityScopeNone";
|
|
1331
|
+
}, {
|
|
1332
|
+
readonly $ref: "#/$defs/AuthorityScopeContexts";
|
|
1333
|
+
}];
|
|
1334
|
+
};
|
|
1335
|
+
readonly AuthorityScopeContexts: {
|
|
1336
|
+
readonly title: "AuthorityScopeContexts";
|
|
1337
|
+
readonly description: "The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.";
|
|
1338
|
+
readonly type: "object";
|
|
1339
|
+
readonly additionalProperties: false;
|
|
1340
|
+
readonly required: readonly ["scope", "contexts"];
|
|
1341
|
+
readonly properties: {
|
|
1342
|
+
readonly scope: {
|
|
1343
|
+
readonly const: "contexts";
|
|
1344
|
+
};
|
|
1345
|
+
readonly contexts: {
|
|
1346
|
+
readonly type: "array";
|
|
1347
|
+
readonly minItems: 1;
|
|
1348
|
+
readonly uniqueItems: true;
|
|
1349
|
+
readonly items: {
|
|
1350
|
+
readonly $ref: "#/$defs/ContextPath";
|
|
1351
|
+
};
|
|
1352
|
+
readonly description: "Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).";
|
|
1353
|
+
};
|
|
1354
|
+
};
|
|
1355
|
+
};
|
|
1356
|
+
readonly ContextPath: {
|
|
1357
|
+
readonly title: "ContextPath";
|
|
1358
|
+
readonly description: "Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.";
|
|
1359
|
+
readonly type: "string";
|
|
1360
|
+
readonly minLength: 1;
|
|
1361
|
+
readonly maxLength: 512;
|
|
1362
|
+
};
|
|
1363
|
+
readonly AuthorityScopeNone: {
|
|
1364
|
+
readonly title: "AuthorityScopeNone";
|
|
1365
|
+
readonly description: "No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.";
|
|
1366
|
+
readonly type: "object";
|
|
1367
|
+
readonly additionalProperties: false;
|
|
1368
|
+
readonly required: readonly ["scope"];
|
|
1369
|
+
readonly properties: {
|
|
1370
|
+
readonly scope: {
|
|
1371
|
+
readonly const: "none";
|
|
1372
|
+
};
|
|
1373
|
+
};
|
|
1374
|
+
};
|
|
1375
|
+
readonly AuthorityScopeAll: {
|
|
1376
|
+
readonly title: "AuthorityScopeAll";
|
|
1377
|
+
readonly description: "Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).";
|
|
1378
|
+
readonly type: "object";
|
|
1379
|
+
readonly additionalProperties: false;
|
|
1380
|
+
readonly required: readonly ["scope"];
|
|
1381
|
+
readonly properties: {
|
|
1382
|
+
readonly scope: {
|
|
1383
|
+
readonly const: "all";
|
|
1384
|
+
};
|
|
1385
|
+
};
|
|
1386
|
+
};
|
|
1387
|
+
};
|
|
1388
|
+
};
|
|
1389
|
+
};
|
|
1390
|
+
/**
|
|
1391
|
+
* SPEC.md §7.2 policy for the success-response variant. `isRecipientRequired`
|
|
1392
|
+
* tracks the *issuer* party's requirement because a response swaps the
|
|
1393
|
+
* parties (§7.3 item 5).
|
|
1394
|
+
*/
|
|
1395
|
+
export declare const RESPONSE_SPEC: {
|
|
1396
|
+
readonly typeUri: "https://trusttasks.org/spec/acl/update/0.2#response";
|
|
1397
|
+
readonly isBearer: false;
|
|
1398
|
+
readonly isProofRequired: true;
|
|
1399
|
+
readonly isRecipientRequired: true;
|
|
1400
|
+
readonly isIssuedAtRequired: true;
|
|
1401
|
+
readonly payloadSchema: {
|
|
1402
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
1403
|
+
readonly $ref: "#/$defs/Response";
|
|
1404
|
+
readonly $defs: {
|
|
1405
|
+
readonly Response: {
|
|
1406
|
+
readonly $anchor: "response";
|
|
1407
|
+
readonly title: "ACL Update 0.2 — response payload";
|
|
1408
|
+
readonly description: "The success response to an acl/update/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/update/0.2#response.";
|
|
1409
|
+
readonly type: "object";
|
|
1410
|
+
readonly additionalProperties: false;
|
|
1411
|
+
readonly required: readonly ["entry"];
|
|
1412
|
+
readonly properties: {
|
|
1413
|
+
readonly entry: {
|
|
1414
|
+
readonly $ref: "#/$defs/AclEntry";
|
|
1415
|
+
readonly description: "The realized entry the maintainer now holds, after the amendment.";
|
|
1416
|
+
};
|
|
1417
|
+
readonly ext: {
|
|
1418
|
+
readonly $ref: "#/$defs/Ext";
|
|
1419
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
1420
|
+
};
|
|
1421
|
+
};
|
|
1422
|
+
};
|
|
1423
|
+
readonly Ext: {
|
|
1424
|
+
readonly title: "Ext";
|
|
1425
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
1426
|
+
readonly type: "object";
|
|
1427
|
+
readonly minProperties: 1;
|
|
1428
|
+
readonly additionalProperties: true;
|
|
1429
|
+
readonly propertyNames: {
|
|
1430
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
1431
|
+
};
|
|
1432
|
+
};
|
|
1433
|
+
readonly AclEntry: {
|
|
1434
|
+
readonly title: "AclEntry";
|
|
1435
|
+
readonly description: "One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).\n\nThe act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer \"may this subject do X\"; `approve` + `approveCapabilities` answer \"may this subject ratify someone else doing X\". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.";
|
|
1436
|
+
readonly type: "object";
|
|
1437
|
+
readonly additionalProperties: false;
|
|
1438
|
+
readonly required: readonly ["subject", "role", "act", "keys", "capabilities"];
|
|
1439
|
+
readonly properties: {
|
|
1440
|
+
readonly subject: {
|
|
1441
|
+
readonly type: "string";
|
|
1442
|
+
readonly minLength: 1;
|
|
1443
|
+
readonly description: "VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.";
|
|
1444
|
+
};
|
|
1445
|
+
readonly role: {
|
|
1446
|
+
readonly type: "string";
|
|
1447
|
+
readonly minLength: 1;
|
|
1448
|
+
readonly description: "Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.";
|
|
1449
|
+
};
|
|
1450
|
+
readonly act: {
|
|
1451
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
1452
|
+
readonly description: "REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{\"scope\": \"all\"}` (unrestricted — every context the maintainer has), `{\"scope\": \"none\"}` (may act nowhere), or `{\"scope\": \"contexts\", \"contexts\": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.";
|
|
1453
|
+
};
|
|
1454
|
+
readonly approve: {
|
|
1455
|
+
readonly $ref: "#/$defs/AuthorityScope";
|
|
1456
|
+
readonly description: "OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{\"scope\": \"none\"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.";
|
|
1457
|
+
};
|
|
1458
|
+
readonly capabilities: {
|
|
1459
|
+
readonly $ref: "#/$defs/CapabilityScope";
|
|
1460
|
+
readonly description: "REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{\"scope\": \"ceiling\"}` (the role's full ceiling, unnarrowed), `{\"scope\": \"none\"}` (no capabilities), or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.";
|
|
1461
|
+
};
|
|
1462
|
+
readonly approveCapabilities: {
|
|
1463
|
+
readonly $ref: "#/$defs/ApproveCapabilityScope";
|
|
1464
|
+
readonly description: "OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{\"scope\": \"ceiling\"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{\"scope\": \"none\"}`, or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{\"scope\": \"none\"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.";
|
|
1465
|
+
};
|
|
1466
|
+
readonly delegatedBy: {
|
|
1467
|
+
readonly type: "string";
|
|
1468
|
+
readonly minLength: 1;
|
|
1469
|
+
readonly description: "VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).";
|
|
1470
|
+
};
|
|
1471
|
+
readonly keys: {
|
|
1472
|
+
readonly $ref: "#/$defs/KeyScope";
|
|
1473
|
+
readonly description: "REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{\"scope\": \"all\"}` (every key the entry's act scope reaches), `{\"scope\": \"none\"}` (no keys), or `{\"scope\": \"listed\", \"keys\": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{\"scope\": \"none\"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.";
|
|
1474
|
+
};
|
|
1475
|
+
readonly label: {
|
|
1476
|
+
readonly type: "string";
|
|
1477
|
+
readonly maxLength: 256;
|
|
1478
|
+
readonly description: "Optional human-readable label. Confers nothing.";
|
|
1479
|
+
};
|
|
1480
|
+
readonly createdAt: {
|
|
1481
|
+
readonly type: "string";
|
|
1482
|
+
readonly format: "date-time";
|
|
1483
|
+
};
|
|
1484
|
+
readonly createdBy: {
|
|
1485
|
+
readonly type: "string";
|
|
1486
|
+
readonly description: "VID of the party that originally wrote this entry.";
|
|
1487
|
+
};
|
|
1488
|
+
readonly updatedAt: {
|
|
1489
|
+
readonly type: "string";
|
|
1490
|
+
readonly format: "date-time";
|
|
1491
|
+
};
|
|
1492
|
+
readonly updatedBy: {
|
|
1493
|
+
readonly type: "string";
|
|
1494
|
+
readonly description: "VID of the party that last modified this entry.";
|
|
1495
|
+
};
|
|
1496
|
+
readonly expiresAt: {
|
|
1497
|
+
readonly type: "string";
|
|
1498
|
+
readonly format: "date-time";
|
|
1499
|
+
readonly description: "Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.";
|
|
1500
|
+
};
|
|
1501
|
+
readonly stepUp: {
|
|
1502
|
+
readonly type: "object";
|
|
1503
|
+
readonly additionalProperties: false;
|
|
1504
|
+
readonly description: "Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.";
|
|
1505
|
+
readonly properties: {
|
|
1506
|
+
readonly approver: {
|
|
1507
|
+
readonly type: "string";
|
|
1508
|
+
readonly description: "VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.";
|
|
1509
|
+
};
|
|
1510
|
+
readonly require: {
|
|
1511
|
+
readonly type: "string";
|
|
1512
|
+
readonly enum: readonly ["self", "delegated"];
|
|
1513
|
+
readonly description: "Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).";
|
|
1514
|
+
};
|
|
1515
|
+
};
|
|
1516
|
+
};
|
|
1517
|
+
readonly ext: {
|
|
1518
|
+
readonly $ref: "#/$defs/Ext";
|
|
1519
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.";
|
|
1520
|
+
};
|
|
1521
|
+
};
|
|
1522
|
+
};
|
|
1523
|
+
readonly KeyScope: {
|
|
1524
|
+
readonly title: "KeyScope";
|
|
1525
|
+
readonly description: "An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.";
|
|
1526
|
+
readonly oneOf: readonly [{
|
|
1527
|
+
readonly $ref: "#/$defs/KeyScopeAll";
|
|
1528
|
+
}, {
|
|
1529
|
+
readonly $ref: "#/$defs/KeyScopeNone";
|
|
1530
|
+
}, {
|
|
1531
|
+
readonly $ref: "#/$defs/KeyScopeListed";
|
|
1532
|
+
}];
|
|
1533
|
+
};
|
|
1534
|
+
readonly KeyScopeListed: {
|
|
1535
|
+
readonly title: "KeyScopeListed";
|
|
1536
|
+
readonly description: "Exactly the listed keys, intersected with the entry's act scope.";
|
|
1537
|
+
readonly type: "object";
|
|
1538
|
+
readonly additionalProperties: false;
|
|
1539
|
+
readonly required: readonly ["scope", "keys"];
|
|
1540
|
+
readonly properties: {
|
|
1541
|
+
readonly scope: {
|
|
1542
|
+
readonly const: "listed";
|
|
1543
|
+
};
|
|
1544
|
+
readonly keys: {
|
|
1545
|
+
readonly type: "array";
|
|
1546
|
+
readonly minItems: 1;
|
|
1547
|
+
readonly uniqueItems: true;
|
|
1548
|
+
readonly items: {
|
|
1549
|
+
readonly type: "string";
|
|
1550
|
+
readonly minLength: 1;
|
|
1551
|
+
readonly maxLength: 512;
|
|
1552
|
+
};
|
|
1553
|
+
readonly description: "Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).";
|
|
1554
|
+
};
|
|
1555
|
+
};
|
|
1556
|
+
};
|
|
1557
|
+
readonly KeyScopeNone: {
|
|
1558
|
+
readonly title: "KeyScopeNone";
|
|
1559
|
+
readonly description: "No keys.";
|
|
1560
|
+
readonly type: "object";
|
|
1561
|
+
readonly additionalProperties: false;
|
|
1562
|
+
readonly required: readonly ["scope"];
|
|
1563
|
+
readonly properties: {
|
|
1564
|
+
readonly scope: {
|
|
1565
|
+
readonly const: "none";
|
|
1566
|
+
};
|
|
1567
|
+
};
|
|
1568
|
+
};
|
|
1569
|
+
readonly KeyScopeAll: {
|
|
1570
|
+
readonly title: "KeyScopeAll";
|
|
1571
|
+
readonly description: "Every key the entry's act scope reaches.";
|
|
1572
|
+
readonly type: "object";
|
|
1573
|
+
readonly additionalProperties: false;
|
|
1574
|
+
readonly required: readonly ["scope"];
|
|
1575
|
+
readonly properties: {
|
|
1576
|
+
readonly scope: {
|
|
1577
|
+
readonly const: "all";
|
|
1578
|
+
};
|
|
1579
|
+
};
|
|
1580
|
+
};
|
|
1581
|
+
readonly ApproveCapabilityScope: {
|
|
1582
|
+
readonly title: "ApproveCapabilityScope";
|
|
1583
|
+
readonly description: "An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.";
|
|
1584
|
+
readonly oneOf: readonly [{
|
|
1585
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
1586
|
+
}, {
|
|
1587
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
1588
|
+
}, {
|
|
1589
|
+
readonly $ref: "#/$defs/ApproveCapabilityScopeListed";
|
|
1590
|
+
}];
|
|
1591
|
+
};
|
|
1592
|
+
readonly ApproveCapabilityScopeListed: {
|
|
1593
|
+
readonly title: "ApproveCapabilityScopeListed";
|
|
1594
|
+
readonly description: "Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.";
|
|
1595
|
+
readonly type: "object";
|
|
1596
|
+
readonly additionalProperties: false;
|
|
1597
|
+
readonly required: readonly ["scope", "grants"];
|
|
1598
|
+
readonly properties: {
|
|
1599
|
+
readonly scope: {
|
|
1600
|
+
readonly const: "listed";
|
|
1601
|
+
};
|
|
1602
|
+
readonly grants: {
|
|
1603
|
+
readonly type: "array";
|
|
1604
|
+
readonly minItems: 1;
|
|
1605
|
+
readonly items: {
|
|
1606
|
+
readonly $ref: "#/$defs/CapabilityRef";
|
|
1607
|
+
};
|
|
1608
|
+
readonly description: "Non-empty list of approvable capabilities. An empty array is invalid.";
|
|
1609
|
+
};
|
|
1610
|
+
};
|
|
1611
|
+
};
|
|
1612
|
+
readonly CapabilityRef: {
|
|
1613
|
+
readonly title: "CapabilityRef";
|
|
1614
|
+
readonly description: "A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.";
|
|
1615
|
+
readonly type: "object";
|
|
1616
|
+
readonly additionalProperties: false;
|
|
1617
|
+
readonly required: readonly ["capability"];
|
|
1618
|
+
readonly properties: {
|
|
1619
|
+
readonly capability: {
|
|
1620
|
+
readonly $ref: "#/$defs/Capability";
|
|
1621
|
+
};
|
|
1622
|
+
readonly resource: {
|
|
1623
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
1624
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
1625
|
+
};
|
|
1626
|
+
};
|
|
1627
|
+
};
|
|
1628
|
+
readonly ResourceQualifier: {
|
|
1629
|
+
readonly title: "ResourceQualifier";
|
|
1630
|
+
readonly description: "Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.";
|
|
1631
|
+
readonly type: "string";
|
|
1632
|
+
readonly minLength: 1;
|
|
1633
|
+
readonly maxLength: 512;
|
|
1634
|
+
};
|
|
1635
|
+
readonly Capability: {
|
|
1636
|
+
readonly title: "Capability";
|
|
1637
|
+
readonly description: "Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.";
|
|
1638
|
+
readonly type: "string";
|
|
1639
|
+
readonly minLength: 1;
|
|
1640
|
+
readonly maxLength: 128;
|
|
1641
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)*$";
|
|
1642
|
+
};
|
|
1643
|
+
readonly CapabilityScopeNone: {
|
|
1644
|
+
readonly title: "CapabilityScopeNone";
|
|
1645
|
+
readonly description: "No capabilities on this axis.";
|
|
1646
|
+
readonly type: "object";
|
|
1647
|
+
readonly additionalProperties: false;
|
|
1648
|
+
readonly required: readonly ["scope"];
|
|
1649
|
+
readonly properties: {
|
|
1650
|
+
readonly scope: {
|
|
1651
|
+
readonly const: "none";
|
|
1652
|
+
};
|
|
1653
|
+
};
|
|
1654
|
+
};
|
|
1655
|
+
readonly CapabilityScopeCeiling: {
|
|
1656
|
+
readonly title: "CapabilityScopeCeiling";
|
|
1657
|
+
readonly description: "The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of \"no narrowing\".";
|
|
1658
|
+
readonly type: "object";
|
|
1659
|
+
readonly additionalProperties: false;
|
|
1660
|
+
readonly required: readonly ["scope"];
|
|
1661
|
+
readonly properties: {
|
|
1662
|
+
readonly scope: {
|
|
1663
|
+
readonly const: "ceiling";
|
|
1664
|
+
};
|
|
1665
|
+
};
|
|
1666
|
+
};
|
|
1667
|
+
readonly CapabilityScope: {
|
|
1668
|
+
readonly title: "CapabilityScope";
|
|
1669
|
+
readonly description: "An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.";
|
|
1670
|
+
readonly oneOf: readonly [{
|
|
1671
|
+
readonly $ref: "#/$defs/CapabilityScopeCeiling";
|
|
1672
|
+
}, {
|
|
1673
|
+
readonly $ref: "#/$defs/CapabilityScopeNone";
|
|
1674
|
+
}, {
|
|
1675
|
+
readonly $ref: "#/$defs/CapabilityScopeListed";
|
|
1676
|
+
}];
|
|
1677
|
+
};
|
|
1678
|
+
readonly CapabilityScopeListed: {
|
|
1679
|
+
readonly title: "CapabilityScopeListed";
|
|
1680
|
+
readonly description: "Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.";
|
|
1681
|
+
readonly type: "object";
|
|
1682
|
+
readonly additionalProperties: false;
|
|
1683
|
+
readonly required: readonly ["scope", "grants"];
|
|
1684
|
+
readonly properties: {
|
|
1685
|
+
readonly scope: {
|
|
1686
|
+
readonly const: "listed";
|
|
1687
|
+
};
|
|
1688
|
+
readonly grants: {
|
|
1689
|
+
readonly type: "array";
|
|
1690
|
+
readonly minItems: 1;
|
|
1691
|
+
readonly items: {
|
|
1692
|
+
readonly $ref: "#/$defs/CapabilityGrant";
|
|
1693
|
+
};
|
|
1694
|
+
readonly description: "Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).";
|
|
1695
|
+
};
|
|
1696
|
+
};
|
|
1697
|
+
};
|
|
1698
|
+
readonly CapabilityGrant: {
|
|
1699
|
+
readonly title: "CapabilityGrant";
|
|
1700
|
+
readonly description: "A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.";
|
|
1701
|
+
readonly type: "object";
|
|
1702
|
+
readonly additionalProperties: false;
|
|
1703
|
+
readonly required: readonly ["capability"];
|
|
1704
|
+
readonly properties: {
|
|
1705
|
+
readonly capability: {
|
|
1706
|
+
readonly $ref: "#/$defs/Capability";
|
|
1707
|
+
};
|
|
1708
|
+
readonly resource: {
|
|
1709
|
+
readonly $ref: "#/$defs/ResourceQualifier";
|
|
1710
|
+
readonly description: "Optional qualifier. Absent covers every resource of the capability's kind.";
|
|
1711
|
+
};
|
|
1712
|
+
readonly additive: {
|
|
1713
|
+
readonly type: "boolean";
|
|
1714
|
+
readonly description: "`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.";
|
|
1715
|
+
};
|
|
1716
|
+
};
|
|
1717
|
+
};
|
|
1718
|
+
readonly AuthorityScope: {
|
|
1719
|
+
readonly title: "AuthorityScope";
|
|
1720
|
+
readonly description: "An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.";
|
|
1721
|
+
readonly oneOf: readonly [{
|
|
1722
|
+
readonly $ref: "#/$defs/AuthorityScopeAll";
|
|
1723
|
+
}, {
|
|
1724
|
+
readonly $ref: "#/$defs/AuthorityScopeNone";
|
|
1725
|
+
}, {
|
|
1726
|
+
readonly $ref: "#/$defs/AuthorityScopeContexts";
|
|
1727
|
+
}];
|
|
1728
|
+
};
|
|
1729
|
+
readonly AuthorityScopeContexts: {
|
|
1730
|
+
readonly title: "AuthorityScopeContexts";
|
|
1731
|
+
readonly description: "The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.";
|
|
1732
|
+
readonly type: "object";
|
|
1733
|
+
readonly additionalProperties: false;
|
|
1734
|
+
readonly required: readonly ["scope", "contexts"];
|
|
1735
|
+
readonly properties: {
|
|
1736
|
+
readonly scope: {
|
|
1737
|
+
readonly const: "contexts";
|
|
1738
|
+
};
|
|
1739
|
+
readonly contexts: {
|
|
1740
|
+
readonly type: "array";
|
|
1741
|
+
readonly minItems: 1;
|
|
1742
|
+
readonly uniqueItems: true;
|
|
1743
|
+
readonly items: {
|
|
1744
|
+
readonly $ref: "#/$defs/ContextPath";
|
|
1745
|
+
};
|
|
1746
|
+
readonly description: "Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).";
|
|
1747
|
+
};
|
|
1748
|
+
};
|
|
1749
|
+
};
|
|
1750
|
+
readonly ContextPath: {
|
|
1751
|
+
readonly title: "ContextPath";
|
|
1752
|
+
readonly description: "Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.";
|
|
1753
|
+
readonly type: "string";
|
|
1754
|
+
readonly minLength: 1;
|
|
1755
|
+
readonly maxLength: 512;
|
|
1756
|
+
};
|
|
1757
|
+
readonly AuthorityScopeNone: {
|
|
1758
|
+
readonly title: "AuthorityScopeNone";
|
|
1759
|
+
readonly description: "No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.";
|
|
1760
|
+
readonly type: "object";
|
|
1761
|
+
readonly additionalProperties: false;
|
|
1762
|
+
readonly required: readonly ["scope"];
|
|
1763
|
+
readonly properties: {
|
|
1764
|
+
readonly scope: {
|
|
1765
|
+
readonly const: "none";
|
|
1766
|
+
};
|
|
1767
|
+
};
|
|
1768
|
+
};
|
|
1769
|
+
readonly AuthorityScopeAll: {
|
|
1770
|
+
readonly title: "AuthorityScopeAll";
|
|
1771
|
+
readonly description: "Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).";
|
|
1772
|
+
readonly type: "object";
|
|
1773
|
+
readonly additionalProperties: false;
|
|
1774
|
+
readonly required: readonly ["scope"];
|
|
1775
|
+
readonly properties: {
|
|
1776
|
+
readonly scope: {
|
|
1777
|
+
readonly const: "all";
|
|
1778
|
+
};
|
|
1779
|
+
};
|
|
1780
|
+
};
|
|
1781
|
+
};
|
|
1782
|
+
};
|
|
1783
|
+
};
|
|
1784
|
+
//# sourceMappingURL=payload.d.ts.map
|