@synoi/gap 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +195 -0
- package/README.md +223 -0
- package/dist/canonicalize.d.ts +19 -0
- package/dist/canonicalize.d.ts.map +1 -0
- package/dist/canonicalize.js +36 -0
- package/dist/canonicalize.js.map +1 -0
- package/dist/capabilities.d.ts +605 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +53 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cdro.d.ts +63 -0
- package/dist/cdro.d.ts.map +1 -0
- package/dist/cdro.js +16 -0
- package/dist/cdro.js.map +1 -0
- package/dist/channels.d.ts +107 -0
- package/dist/channels.d.ts.map +1 -0
- package/dist/channels.js +29 -0
- package/dist/channels.js.map +1 -0
- package/dist/constants.d.ts +32 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +36 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/oid.d.ts +28 -0
- package/dist/oid.d.ts.map +1 -0
- package/dist/oid.js +68 -0
- package/dist/oid.js.map +1 -0
- package/dist/receipts.d.ts +128 -0
- package/dist/receipts.d.ts.map +1 -0
- package/dist/receipts.js +14 -0
- package/dist/receipts.js.map +1 -0
- package/dist/revocations.d.ts +65 -0
- package/dist/revocations.d.ts.map +1 -0
- package/dist/revocations.js +22 -0
- package/dist/revocations.js.map +1 -0
- package/dist/validate.d.ts +59 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +835 -0
- package/dist/validate.js.map +1 -0
- package/dist/workflows.d.ts +186 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +14 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +55 -0
- package/src/canonicalize.ts +38 -0
- package/src/capabilities.ts +711 -0
- package/src/cdro.ts +92 -0
- package/src/channels.ts +183 -0
- package/src/constants.ts +46 -0
- package/src/index.ts +180 -0
- package/src/oid.ts +71 -0
- package/src/receipts.ts +169 -0
- package/src/revocations.ts +90 -0
- package/src/validate.ts +1008 -0
- package/src/workflows.ts +241 -0
package/src/receipts.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* receipts.ts -- GAP Decision Receipts.
|
|
3
|
+
*
|
|
4
|
+
* Every gate decision (capability invocation, workflow transition, grant
|
|
5
|
+
* issuance/revocation, federation handshake (reserved for GAP 1.1), provisional block) produces
|
|
6
|
+
* an immutable Decision Receipt. These are the audit trail of the agent
|
|
7
|
+
* platform -- what was allowed, what was denied, when, and by whom.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors GAP_SPEC §8.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { GapCdroEnvelope } from './cdro.js'
|
|
13
|
+
import type { GapActorType } from './capabilities.js'
|
|
14
|
+
|
|
15
|
+
export type DecisionSubjectKind =
|
|
16
|
+
| 'capability_invocation'
|
|
17
|
+
| 'stage_transition'
|
|
18
|
+
| 'grant_issued'
|
|
19
|
+
| 'grant_revoked'
|
|
20
|
+
| 'workflow_started'
|
|
21
|
+
| 'workflow_terminated'
|
|
22
|
+
| 'revocation_initiated'
|
|
23
|
+
| 'revocation_effective'
|
|
24
|
+
| 'federation_handshake' // reserved for GAP 1.1 - not part of the active 1.0 conformance surface
|
|
25
|
+
| 'provisional_block'
|
|
26
|
+
|
|
27
|
+
export type DecisionStatus =
|
|
28
|
+
| 'ok'
|
|
29
|
+
| 'denied'
|
|
30
|
+
| 'failed'
|
|
31
|
+
| 'deferred'
|
|
32
|
+
| 'timed_out'
|
|
33
|
+
| 'pending'
|
|
34
|
+
| 'rate_limited'
|
|
35
|
+
|
|
36
|
+
export interface GapDecisionReceiptBody {
|
|
37
|
+
subject_kind: DecisionSubjectKind
|
|
38
|
+
subject_oid: string
|
|
39
|
+
initiator: {
|
|
40
|
+
actor_oid: string
|
|
41
|
+
actor_type: GapActorType
|
|
42
|
+
}
|
|
43
|
+
status: DecisionStatus
|
|
44
|
+
detail?: string
|
|
45
|
+
capability_grant_oids?: string[]
|
|
46
|
+
workflow_instance_oid?: string
|
|
47
|
+
workflow_stage_id?: string
|
|
48
|
+
inference_receipt_oid?: string
|
|
49
|
+
channel_event_oids?: string[]
|
|
50
|
+
initiated_at_ms: number
|
|
51
|
+
resolved_at_ms: number
|
|
52
|
+
metrics?: {
|
|
53
|
+
latency_ms?: number
|
|
54
|
+
channel_count?: number
|
|
55
|
+
listen_match_count?: number
|
|
56
|
+
}
|
|
57
|
+
compliance_tags?: string[]
|
|
58
|
+
/**
|
|
59
|
+
* True when this receipt was served from the idempotency deduplication cache
|
|
60
|
+
* rather than freshly evaluated. The cached args and grant state at the time
|
|
61
|
+
* of original evaluation apply; this is NOT a fresh gate decision.
|
|
62
|
+
*/
|
|
63
|
+
is_idempotency_replay?: boolean
|
|
64
|
+
/**
|
|
65
|
+
* The client-supplied `invoked_at_ms` value from the invocation body,
|
|
66
|
+
* preserved here for debugging only. MUST NOT be used as `initiated_at_ms`.
|
|
67
|
+
* The gateway always server-stamps `initiated_at_ms`.
|
|
68
|
+
*/
|
|
69
|
+
client_claimed_at_ms?: number
|
|
70
|
+
/**
|
|
71
|
+
* For receipts covering physical_safety=true capabilities: constrained
|
|
72
|
+
* devices performing offline Ed25519 signature verification MUST NOT accept
|
|
73
|
+
* this receipt after this TTL has elapsed (milliseconds since epoch).
|
|
74
|
+
* Absent means no offline TTL is enforced by the protocol (gateway-level
|
|
75
|
+
* policy may still apply).
|
|
76
|
+
*/
|
|
77
|
+
max_offline_ttl_ms?: number
|
|
78
|
+
/**
|
|
79
|
+
* For 21 CFR Part 11 contexts: display name, role, and credential identifier
|
|
80
|
+
* of the authorizing human. The `granted_by` actor OID SHOULD resolve to
|
|
81
|
+
* this identity. Gateway-populated when the deployment asserts 21 CFR Part 11
|
|
82
|
+
* compliance and the receipt covers a medical device / clinical capability.
|
|
83
|
+
*/
|
|
84
|
+
signer_identity?: {
|
|
85
|
+
display_name: string
|
|
86
|
+
role?: string
|
|
87
|
+
credential_id?: string
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* C8: Sub-millisecond sequence numbers (GAP spec section Phase 4).
|
|
91
|
+
*
|
|
92
|
+
* Monotonically increasing integer within the tenant, incremented per receipt,
|
|
93
|
+
* gapless. Gaps in the sequence indicate dropped receipts. Provides
|
|
94
|
+
* determinable ordering within a millisecond for high-frequency deployments
|
|
95
|
+
* (MiFID II RTS 25). A gateway MUST guarantee strict monotonicity within a
|
|
96
|
+
* tenant.
|
|
97
|
+
*/
|
|
98
|
+
sequence_number?: number
|
|
99
|
+
/**
|
|
100
|
+
* C8: Optional nanoseconds since Unix epoch for sub-millisecond precision.
|
|
101
|
+
* RECOMMENDED for financial.* capabilities. Complements decided_at_ms
|
|
102
|
+
* (the spec's alias for resolved_at_ms) when nanosecond ordering matters.
|
|
103
|
+
*/
|
|
104
|
+
decided_at_ns?: number
|
|
105
|
+
/**
|
|
106
|
+
* Item 3 [DESIGN]: Settled token consumption for this invocation. Populated
|
|
107
|
+
* by the gateway post-invoke when the 'token_budget' precondition is active.
|
|
108
|
+
* input_tokens and output_tokens MUST be non-negative integers.
|
|
109
|
+
*/
|
|
110
|
+
token_consumption?: TokenConsumption
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// -- Item 3: Token Consumption -----------------------------------------------
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* [DESIGN] Actual token usage settled onto the receipt by the gateway after
|
|
117
|
+
* execution. Used by the 'token_budget' precondition (post_invoke evaluation).
|
|
118
|
+
* Any cost_usd figures are [MODELED] until a conformance vector exists.
|
|
119
|
+
*/
|
|
120
|
+
export interface TokenConsumption {
|
|
121
|
+
/** Input (prompt) tokens consumed. Must be a non-negative integer. */
|
|
122
|
+
input_tokens: number
|
|
123
|
+
/** Output (completion) tokens consumed. Must be a non-negative integer. */
|
|
124
|
+
output_tokens: number
|
|
125
|
+
/** Model identifier that produced the tokens. */
|
|
126
|
+
model: string
|
|
127
|
+
/** Estimated cost in USD. [MODELED] -- not authoritative until conformance vector exists. */
|
|
128
|
+
cost_usd?: number
|
|
129
|
+
/** Unix epoch ms when consumption was settled. */
|
|
130
|
+
settled_at_ms: number
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export type GapDecisionReceipt = GapCdroEnvelope<GapDecisionReceiptBody>
|
|
134
|
+
|
|
135
|
+
// -- Failure typing (non-CDRO; in-process return shape) ----------------------
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* In-process failure classification returned by gate helpers and SDK utilities.
|
|
139
|
+
* This is an internal enum and does NOT appear on the wire.
|
|
140
|
+
*
|
|
141
|
+
* The wire `detail` field in `GapDecisionReceipt.body.detail` uses the
|
|
142
|
+
* namespaced error codes from ERROR_CODES.md, for example:
|
|
143
|
+
* capability_denied:no_grant
|
|
144
|
+
* capability_denied:grant_expired
|
|
145
|
+
* capability_denied:grant_revoked
|
|
146
|
+
* capability_denied:rate_limited
|
|
147
|
+
* Do NOT expose GapFailureReason values in serialized receipts or HTTP responses.
|
|
148
|
+
*/
|
|
149
|
+
export type GapFailureReason =
|
|
150
|
+
| 'capability_not_found'
|
|
151
|
+
| 'capability_denied'
|
|
152
|
+
| 'capability_revoked'
|
|
153
|
+
| 'precondition_failed'
|
|
154
|
+
| 'rate_limited'
|
|
155
|
+
| 'grant_expired'
|
|
156
|
+
| 'workflow_not_found'
|
|
157
|
+
| 'workflow_revoked'
|
|
158
|
+
| 'missing_required_channels'
|
|
159
|
+
| 'execution_failed'
|
|
160
|
+
|
|
161
|
+
export interface GapFailure {
|
|
162
|
+
reason: GapFailureReason
|
|
163
|
+
detail?: string
|
|
164
|
+
receipt_oid: string
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function isGapFailure<T>(r: T | GapFailure): r is GapFailure {
|
|
168
|
+
return typeof r === 'object' && r !== null && 'reason' in (r as Record<string, unknown>)
|
|
169
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* revocations.ts -- RevocationEvent CDRO.
|
|
3
|
+
*
|
|
4
|
+
* Revocation in GAP is leveled (L1 / L2 / L3) per GAP_SPEC §7. V1 gateway
|
|
5
|
+
* scope is L1 only; L2/L3 fields are tracked here for forward compatibility.
|
|
6
|
+
*
|
|
7
|
+
* Targets include declarations, grants, workflow definitions, workflow
|
|
8
|
+
* instances, and whole skills. A revocation can be provisional (immediately
|
|
9
|
+
* blocks but pending finalization) or final.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { GapCdroEnvelope } from './cdro.js'
|
|
13
|
+
|
|
14
|
+
export type RevocationTargetKind =
|
|
15
|
+
| 'capability_declaration'
|
|
16
|
+
| 'capability_grant'
|
|
17
|
+
| 'workflow_definition'
|
|
18
|
+
| 'workflow_instance'
|
|
19
|
+
| 'skill'
|
|
20
|
+
|
|
21
|
+
export interface RevocationEventBody {
|
|
22
|
+
target_kind: RevocationTargetKind
|
|
23
|
+
target_oid: string
|
|
24
|
+
reason: string
|
|
25
|
+
evidence_oids?: string[]
|
|
26
|
+
required_level: 1 | 2 | 3
|
|
27
|
+
provisional: boolean
|
|
28
|
+
approvers: Array<{
|
|
29
|
+
actor_oid: string
|
|
30
|
+
approved_at_ms: number
|
|
31
|
+
cooling_off_satisfied: boolean
|
|
32
|
+
attestation_oid?: string
|
|
33
|
+
}>
|
|
34
|
+
public_notice_started_at_ms?: number
|
|
35
|
+
public_notice_window_ms?: number
|
|
36
|
+
effective_at_ms: number | null
|
|
37
|
+
lifted_at_ms?: number | null
|
|
38
|
+
/**
|
|
39
|
+
* Controls what happens when a provisional block's TTL expires without the
|
|
40
|
+
* required L3 quorum completing:
|
|
41
|
+
* 'renew' -- the block auto-renews (fail-closed). Default, and MUST be
|
|
42
|
+
* the behavior when any targeted grant covers a capability
|
|
43
|
+
* with physical_safety=true or safety_class='C'.
|
|
44
|
+
* 'revert' -- the block expires and the target is re-enabled. Only
|
|
45
|
+
* permissible for safety_class A/B capabilities with explicit
|
|
46
|
+
* operator override.
|
|
47
|
+
*
|
|
48
|
+
* Absent defaults to 'renew' for physical safety targets, 'revert' for
|
|
49
|
+
* others (legacy behavior). Gateways MUST treat absent-for-physical-safety
|
|
50
|
+
* as 'renew'.
|
|
51
|
+
*/
|
|
52
|
+
provisional_block_policy?: {
|
|
53
|
+
on_expiry_without_quorum: 'renew' | 'revert'
|
|
54
|
+
/**
|
|
55
|
+
* M-5: Operator override for the provisional block TTL. Defaults to 72
|
|
56
|
+
* hours (259_200_000 ms). Minimum: 1 hour (3_600_000 ms). For
|
|
57
|
+
* safety_class C capabilities with on_expiry_without_quorum='renew', the
|
|
58
|
+
* renewal cycle period equals this value.
|
|
59
|
+
*/
|
|
60
|
+
provisional_block_ttl_ms?: number
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Minimum number of distinct approvers required to make `effective_at_ms`
|
|
64
|
+
* non-null. Default: 1 for L2, gateway-configured for L3 (recommended >= 2).
|
|
65
|
+
* The gateway MUST reject a duplicate approval from the same actor_oid.
|
|
66
|
+
* Self-approval (approver actor_oid === revocation event created_by) MUST
|
|
67
|
+
* be rejected.
|
|
68
|
+
*/
|
|
69
|
+
min_approvers?: number
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type RevocationEvent = GapCdroEnvelope<RevocationEventBody>
|
|
73
|
+
|
|
74
|
+
export function revokeGapObject(
|
|
75
|
+
target_kind: RevocationTargetKind,
|
|
76
|
+
target_oid: string,
|
|
77
|
+
reason: string,
|
|
78
|
+
required_level: 1 | 2 | 3,
|
|
79
|
+
provisional: boolean,
|
|
80
|
+
): RevocationEventBody {
|
|
81
|
+
return {
|
|
82
|
+
target_kind,
|
|
83
|
+
target_oid,
|
|
84
|
+
reason,
|
|
85
|
+
required_level,
|
|
86
|
+
provisional,
|
|
87
|
+
approvers: [],
|
|
88
|
+
effective_at_ms: null,
|
|
89
|
+
}
|
|
90
|
+
}
|