@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.
Files changed (58) hide show
  1. package/LICENSE +195 -0
  2. package/README.md +223 -0
  3. package/dist/canonicalize.d.ts +19 -0
  4. package/dist/canonicalize.d.ts.map +1 -0
  5. package/dist/canonicalize.js +36 -0
  6. package/dist/canonicalize.js.map +1 -0
  7. package/dist/capabilities.d.ts +605 -0
  8. package/dist/capabilities.d.ts.map +1 -0
  9. package/dist/capabilities.js +53 -0
  10. package/dist/capabilities.js.map +1 -0
  11. package/dist/cdro.d.ts +63 -0
  12. package/dist/cdro.d.ts.map +1 -0
  13. package/dist/cdro.js +16 -0
  14. package/dist/cdro.js.map +1 -0
  15. package/dist/channels.d.ts +107 -0
  16. package/dist/channels.d.ts.map +1 -0
  17. package/dist/channels.js +29 -0
  18. package/dist/channels.js.map +1 -0
  19. package/dist/constants.d.ts +32 -0
  20. package/dist/constants.d.ts.map +1 -0
  21. package/dist/constants.js +36 -0
  22. package/dist/constants.js.map +1 -0
  23. package/dist/index.d.ts +28 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +35 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/oid.d.ts +28 -0
  28. package/dist/oid.d.ts.map +1 -0
  29. package/dist/oid.js +68 -0
  30. package/dist/oid.js.map +1 -0
  31. package/dist/receipts.d.ts +128 -0
  32. package/dist/receipts.d.ts.map +1 -0
  33. package/dist/receipts.js +14 -0
  34. package/dist/receipts.js.map +1 -0
  35. package/dist/revocations.d.ts +65 -0
  36. package/dist/revocations.d.ts.map +1 -0
  37. package/dist/revocations.js +22 -0
  38. package/dist/revocations.js.map +1 -0
  39. package/dist/validate.d.ts +59 -0
  40. package/dist/validate.d.ts.map +1 -0
  41. package/dist/validate.js +835 -0
  42. package/dist/validate.js.map +1 -0
  43. package/dist/workflows.d.ts +186 -0
  44. package/dist/workflows.d.ts.map +1 -0
  45. package/dist/workflows.js +14 -0
  46. package/dist/workflows.js.map +1 -0
  47. package/package.json +55 -0
  48. package/src/canonicalize.ts +38 -0
  49. package/src/capabilities.ts +711 -0
  50. package/src/cdro.ts +92 -0
  51. package/src/channels.ts +183 -0
  52. package/src/constants.ts +46 -0
  53. package/src/index.ts +180 -0
  54. package/src/oid.ts +71 -0
  55. package/src/receipts.ts +169 -0
  56. package/src/revocations.ts +90 -0
  57. package/src/validate.ts +1008 -0
  58. package/src/workflows.ts +241 -0
@@ -0,0 +1,605 @@
1
+ /**
2
+ * capabilities.ts -- Declaration / Grant / Invocation shapes.
3
+ *
4
+ * These mirror the GAP gateway reference implementation wire types.
5
+ * The trio is the GAP operational core:
6
+ *
7
+ * - CapabilityDeclaration: an actor announces "I can do X under conditions Y".
8
+ * - CapabilityGrant: an operator says "actor A may invoke X within scope S until time T".
9
+ * - CapabilityInvocation: an actor performs "I am invoking X, here are my args + the grant I'm using".
10
+ *
11
+ * Every gate check (grant exists + not revoked + not expired + scope matches
12
+ * + preconditions hold) happens on invocation. The decision becomes a
13
+ * GapDecisionReceipt.
14
+ */
15
+ import type { GapCdroEnvelope } from './cdro.js';
16
+ export type GapActorType = 'skill' | 'service' | 'device' | 'agent' | 'mcp_server' | 'gateway_subsystem' | 'human_user';
17
+ /**
18
+ * [DESIGN] One hop in a gap:orchestration_chain. Each step signs over the
19
+ * prior step receipt OID plus the canonical invocation body. Signing keys for
20
+ * each hop MUST be declared at grant issuance.
21
+ */
22
+ export interface DelegationStep {
23
+ /** Zero-based index of this hop in the chain. */
24
+ step_index: number;
25
+ /** Actor OID performing the delegation. */
26
+ delegator_actor_oid: string;
27
+ /** Actor OID receiving delegated authority. */
28
+ delegatee_actor_oid: string;
29
+ /** OID of the grant that authorizes this delegation hop. */
30
+ grant_oid: string;
31
+ /** OID of the receipt from the prior hop (absent for step_index 0). */
32
+ prior_receipt_oid?: string;
33
+ /** Unix epoch ms when delegation was issued. */
34
+ delegated_at_ms: number;
35
+ /** Signature over canonical(prior_receipt_oid + invocation_body), base64url. */
36
+ step_signature: string;
37
+ /** Algorithm used for step_signature, e.g. 'Ed25519' or 'ML-DSA-65'. */
38
+ step_signature_alg: string;
39
+ }
40
+ /**
41
+ * [DESIGN] Body of a gap:orchestration_chain CDRO. Consolidates all delegation
42
+ * hops into one envelope. The gateway MUST verify each step's signature before
43
+ * allowing the terminal invocation.
44
+ *
45
+ * Max hops: 10. Gateway returns HTTP 400 with error 'delegation_depth_exceeded'
46
+ * when steps.length > 10.
47
+ */
48
+ export interface OrchestrationChainBody {
49
+ /** Actor OID that initiated the chain. */
50
+ root_actor_oid: string;
51
+ /** Ordered array of delegation steps, max 10. */
52
+ steps: DelegationStep[];
53
+ /** Capability name being delegated through the chain. */
54
+ capability_name: string;
55
+ /** OID of the terminal invocation CDRO this chain authorizes. */
56
+ final_invocation_oid: string;
57
+ }
58
+ /**
59
+ * [DESIGN] Context attached to an invocation when the capability originated
60
+ * from an MCP tools/list response. Capability names for MCP tools follow the
61
+ * pattern mcp.<server_id>.<tool_name>.
62
+ *
63
+ * The gateway MUST reject any auto-generated capability name that starts with
64
+ * 'gap:' or matches any normative capability name, to prevent namespace
65
+ * pollution from attacker-controlled tools/list responses.
66
+ */
67
+ export interface McpToolCallContext {
68
+ /** Stable identifier for the MCP server. */
69
+ server_id: string;
70
+ /** Name of the tool as returned by tools/list. */
71
+ tool_name: string;
72
+ /** Optional SHA-256 hash of the tool's JSON schema, for drift detection. */
73
+ tool_schema_hash?: string;
74
+ }
75
+ /**
76
+ * [DESIGN] Args for the 'token_budget' precondition kind. Evaluation timing:
77
+ * post_invoke (settled after execution). Any cost figures MUST carry [MODELED]
78
+ * tag until a conformance vector exists.
79
+ */
80
+ export interface TokenBudgetArgs {
81
+ /**
82
+ * Model ID pattern using shell-glob syntax, e.g. 'anthropic/claude-*'.
83
+ * Matched against the model identifier on the receipt's token_consumption.
84
+ */
85
+ model_scope: string;
86
+ /** Maximum input tokens permitted within window_seconds. */
87
+ max_input_tokens?: number;
88
+ /** Maximum output tokens permitted within window_seconds. */
89
+ max_output_tokens?: number;
90
+ /** Maximum cost in USD permitted within window_seconds. [MODELED] */
91
+ max_cost_usd?: number;
92
+ /** Rolling window length in seconds. */
93
+ window_seconds: number;
94
+ }
95
+ /**
96
+ * [DESIGN] Body of a gap:consent_record CDRO. Forms an append-only chain via
97
+ * prior_consent_oid. The precondition kind 'consent_current' evaluates whether
98
+ * the actor's most recent consent record has consented: true.
99
+ *
100
+ * MUST: the gateway MUST NOT use the idempotency cache for consent_current
101
+ * evaluation. Withdrawal (consented: false) MUST take effect within 5 seconds
102
+ * across all replicas.
103
+ *
104
+ * This single primitive subsumes hiring consent, learner consent, and clinical
105
+ * consent. The context field carries sector-specific detail.
106
+ */
107
+ export interface ConsentRecordBody {
108
+ /** Actor OID whose consent this record captures. */
109
+ actor_oid: string;
110
+ /** Tenant scope of the consent. */
111
+ tenant_id: string;
112
+ /**
113
+ * Free-form context string identifying the consent subject, e.g.
114
+ * 'hiring.background_check', 'clinical.data_sharing', 'learner.analytics'.
115
+ */
116
+ context: string;
117
+ /** True = consent granted; false = consent withdrawn. */
118
+ consented: boolean;
119
+ /** OID of the prior consent record for this actor + context, forming the chain. */
120
+ prior_consent_oid?: string;
121
+ /** Unix epoch ms when consent was recorded. */
122
+ consented_at_ms: number;
123
+ /** Optional expiry; gateway MUST treat expired records as consented: false. */
124
+ expires_at_ms?: number;
125
+ /** SHA-256 hash of the consent disclosure text shown to the actor. */
126
+ consent_text_hash?: string;
127
+ }
128
+ /**
129
+ * [DESIGN] Normative credential_kind values for IdentityBinding. The binding
130
+ * ties an actor_oid to a real-world credential with a hardware-backed signature.
131
+ */
132
+ export type CredentialKind = 'piv_cac' | 'x509' | 'fido2' | 'tpm_attestation' | 'oidc_sub' | 'spiffe_svid' | 'wallet_address' | 'professional_license';
133
+ /**
134
+ * [DESIGN] Ties an actor_oid to a real-world credential. The canonical binding
135
+ * payload (domain-separated) is:
136
+ * "gap-identity-binding-v1" + ":" + actor_oid + ":" + tenant_id + ":" + credential_identifier
137
+ *
138
+ * The binding_signature is a credential holder's signature over that payload.
139
+ */
140
+ export interface IdentityBinding {
141
+ /** Normative credential kind. */
142
+ credential_kind: CredentialKind;
143
+ /** Stable identifier within the credential_kind namespace (e.g. certificate serial, SPIFFE SVID URI). */
144
+ credential_identifier: string;
145
+ /** Signature over the domain-separated canonical payload, base64url. */
146
+ binding_signature: string;
147
+ /** Algorithm used for binding_signature, e.g. 'Ed25519', 'ES256', 'RS256'. */
148
+ binding_alg: string;
149
+ /** Unix epoch ms when binding was established. */
150
+ bound_at_ms: number;
151
+ /** Issuer identifier (CA DN, OIDC issuer URL, etc.) -- optional but RECOMMENDED. */
152
+ issuer?: string;
153
+ /** Unix epoch ms when binding expires. Absent = no expiry. */
154
+ expires_at_ms?: number;
155
+ }
156
+ /**
157
+ * [DESIGN] Args for the 'external_pip' precondition kind. The gateway POSTs
158
+ * invocation args to the endpoint and evaluates the boolean `allowed` response.
159
+ * When pip_response_oid is set, the referenced gap:pip_response CDRO is
160
+ * ENFORCING; the gateway MUST verify its signature before using it as the sole
161
+ * basis for an allow decision. Unsigned reads without pip_response_oid are
162
+ * ADVISORY only.
163
+ */
164
+ export interface ExternalPipArgs {
165
+ /** URL of the external Policy Information Point. */
166
+ endpoint_url: string;
167
+ /** Cache TTL in seconds for the PIP response, keyed by (tenant, capability, args-hash). */
168
+ cache_ttl_seconds: number;
169
+ /** Invocation arg keys sent to the PIP as subject context. */
170
+ subject_fields: string[];
171
+ /**
172
+ * [DESIGN] OID of a gap:pip_response CDRO. When present, the gateway MUST
173
+ * verify the CDRO signature before treating the response as ENFORCING.
174
+ * Absent = response is ADVISORY.
175
+ */
176
+ pip_response_oid?: string;
177
+ }
178
+ /**
179
+ * [DESIGN] Body of a gap:pip_response CDRO. Emitted by an external PIP and
180
+ * re-signed by the gateway. Distinction:
181
+ * - Unsigned external reads: ADVISORY (influence decision; cannot be sole basis for allow).
182
+ * - Signed gap:pip_response: ENFORCING (gateway may use as sole basis for allow/deny).
183
+ *
184
+ * The gateway MUST verify the CDRO signature before treating the response as
185
+ * enforcing.
186
+ */
187
+ export interface PipResponseBody {
188
+ /** URL of the external PIP endpoint that produced this response. */
189
+ pip_endpoint: string;
190
+ /** SHA-256 hash of the canonical request args sent to the PIP. */
191
+ request_args_hash: string;
192
+ /** SHA-256 hash of the raw response body received from the PIP. */
193
+ response_body_hash: string;
194
+ /** Optional human-readable summary of the PIP response (not authoritative). */
195
+ response_summary?: string;
196
+ /** Unix epoch ms when the PIP was queried. */
197
+ evaluated_at_ms: number;
198
+ /** How long (ms) this response may be cached by the gateway. */
199
+ cache_ttl_ms: number;
200
+ /** Optional signature from the PIP itself over the response body, base64url. */
201
+ pip_signature?: string;
202
+ /** Algorithm used for pip_signature. */
203
+ pip_signature_alg?: string;
204
+ }
205
+ export interface CapabilityPredicate {
206
+ kind: string;
207
+ args: Record<string, unknown>;
208
+ }
209
+ export interface Capability {
210
+ /** Dotted-taxonomy capability name, e.g. `skill.create`, `gap.discovery.query`. */
211
+ capability: string;
212
+ /** Capability-level scope constraints (free-form per-capability). */
213
+ scope?: Record<string, unknown>;
214
+ /** Preconditions evaluated at invocation gate. */
215
+ preconditions?: CapabilityPredicate[];
216
+ /** Safety classification: A (low) / B (medium) / C (high). */
217
+ safety_class?: 'A' | 'B' | 'C';
218
+ /** True if invocation can change physical-world state (HA, IoT, etc.). */
219
+ physical_safety?: boolean;
220
+ /**
221
+ * When true, the gateway MUST attach a cryptographic signature to every
222
+ * decision receipt for this capability, regardless of the server's default
223
+ * conformance tier. When false, the gateway SHOULD omit the signature even
224
+ * on an L4 server (useful for high-frequency trivial actions where signing
225
+ * cost outweighs the benefit). When absent, the gateway applies its
226
+ * configured default signing policy.
227
+ *
228
+ * The operator may override this on the grant via
229
+ * GrantedCapabilityScope.require_signed_receipt.
230
+ */
231
+ require_signed_receipt?: boolean;
232
+ /**
233
+ * Array of invocation arg key strings whose values contain PII, PHI, or NPI
234
+ * requiring tokenization before storage. The gateway MUST replace each listed
235
+ * key's value with a keyed HMAC token (one-way, using a per-tenant key)
236
+ * before constructing the invocation CDRO and receipt body. The original
237
+ * value is used for capability execution by the adapter but MUST NOT be
238
+ * stored in any CDRO.
239
+ *
240
+ * Required for capabilities with privacy_classification 'phi' or whose name
241
+ * matches medical.* or financial.*.
242
+ */
243
+ pii_args?: string[];
244
+ /**
245
+ * C17: When true, the gateway routes receipts for this capability to a
246
+ * privilege-isolated store, suppresses them from the standard GET /receipts
247
+ * list endpoint, requires an explicit attorney-assertion header on fetch by
248
+ * OID, and excludes the receipt from automated compliance exports.
249
+ * Controls access routing, not deletion.
250
+ */
251
+ privilege_protected?: boolean;
252
+ }
253
+ export interface CapabilityDeclarationBody {
254
+ actor_type: GapActorType;
255
+ actor_id: string;
256
+ actor_name: string;
257
+ actor_version: string;
258
+ source_url?: string;
259
+ parent_oid?: string;
260
+ capabilities: Capability[];
261
+ /**
262
+ * C15: Ephemeral actor lifecycle (GAP spec Phase 1 -- Ephemeral Actors).
263
+ *
264
+ * `persistent` (default) -- standard supersession uniqueness rules apply.
265
+ * `ephemeral` -- declaration is exempt from supersession uniqueness; each
266
+ * invocation gets a fresh OID valid for its session only.
267
+ */
268
+ actor_lifecycle?: 'persistent' | 'ephemeral';
269
+ /**
270
+ * C15: UUID or job ID distinguishing this instance from others with the same
271
+ * actor_id. When present, two declarations with the same actor_id but
272
+ * different actor_instance_id MUST NOT be treated as superseding each other.
273
+ */
274
+ actor_instance_id?: string;
275
+ /**
276
+ * C15: For ephemeral actors: when this session ends (Unix epoch ms). The
277
+ * gateway MUST auto-revoke all grants scoped to this actor_instance_id at
278
+ * this time.
279
+ */
280
+ session_expires_at_ms?: number;
281
+ declared_limits?: {
282
+ max_invocations_per_minute?: number;
283
+ max_concurrent_invocations?: number;
284
+ max_payload_bytes?: number;
285
+ requires_network?: boolean;
286
+ requires_filesystem_read?: string[];
287
+ requires_filesystem_write?: string[];
288
+ };
289
+ human_summary?: string;
290
+ privacy_classification?: 'public' | 'restricted' | 'sensitive' | 'phi' | 'pii' | 'financial' | 'privileged';
291
+ /**
292
+ * Item 5 [DESIGN]: Real-world credential binding for this actor. Ties the
293
+ * actor_oid to a verifiable credential using a hardware-backed signature.
294
+ * See IdentityBinding for the canonical payload and domain-separation prefix.
295
+ */
296
+ identity_binding?: IdentityBinding;
297
+ /**
298
+ * Item 6 [DESIGN]: Compartment label for this declaration.
299
+ * Values: 'UNCLASS', 'CUI', or a reverse-domain operator label
300
+ * (e.g. 'com.acme.project-alpha').
301
+ */
302
+ compartment?: string;
303
+ }
304
+ export type CapabilityDeclaration = GapCdroEnvelope<CapabilityDeclarationBody>;
305
+ export interface GrantedCapabilityScope {
306
+ capability: string;
307
+ /**
308
+ * OID of the specific capability declaration envelope this scope is pinned to.
309
+ * REQUIRED for grants covering safety_class='C' or physical_safety=true
310
+ * capabilities. The gateway evaluates those grants against this pinned
311
+ * declaration OID rather than the actor's current active declaration,
312
+ * preventing declaration supersession attacks.
313
+ */
314
+ capability_declaration_oid?: string;
315
+ scope_narrowing?: Record<string, unknown>;
316
+ additional_preconditions?: CapabilityPredicate[];
317
+ /**
318
+ * M-4: Operator override for receipt signing on this specific scope. When
319
+ * set, takes precedence over the capability declaration's
320
+ * require_signed_receipt. Allows a compliance deployment to require signed
321
+ * receipts for every action regardless of what the actor declared.
322
+ */
323
+ require_signed_receipt?: boolean;
324
+ }
325
+ export interface CapabilityGrantBody {
326
+ grantee: {
327
+ actor_type: GapActorType;
328
+ actor_oid: string;
329
+ actor_session_id?: string;
330
+ };
331
+ capability_scopes: GrantedCapabilityScope[];
332
+ granted_at_ms: number;
333
+ expires_at_ms: number | null;
334
+ limits?: {
335
+ max_invocations_per_minute?: number;
336
+ max_invocations_total?: number;
337
+ max_payload_bytes?: number;
338
+ /**
339
+ * Rolling-window aggregate constraints. Each entry specifies an invocation
340
+ * args key to sum across invocations and a ceiling within a rolling time
341
+ * window. Example: { key: 'amount_usd', max: 10000, window_seconds: 3600 }
342
+ * denies invocations that would push the rolling sum above $10,000/hr.
343
+ * Enables financial controls that a per-invocation cap cannot provide.
344
+ */
345
+ aggregate_limits?: Array<{
346
+ /** Invocation args key to aggregate (must be a numeric value). */
347
+ key: string;
348
+ /** Maximum allowed sum within the rolling window. */
349
+ max: number;
350
+ /** Length of the rolling window in seconds. */
351
+ window_seconds: number;
352
+ }>;
353
+ /**
354
+ * Named pool identifier for cross-grant aggregate limit groups. All grants
355
+ * with the same aggregate_limit_group share rolling aggregate counters
356
+ * defined in the tenant's pool configuration. The gateway MUST maintain
357
+ * atomic counters per pool and MUST deny any invocation from any grant in
358
+ * the pool that would exceed the pool ceiling.
359
+ */
360
+ aggregate_limit_group?: string;
361
+ };
362
+ granted_by: string;
363
+ reason?: string;
364
+ evidence_oids?: string[];
365
+ revocation_level_override?: 1 | 2 | 3;
366
+ /**
367
+ * Operator override for receipt signing on a per-scope basis. When set,
368
+ * takes precedence over the capability declaration's require_signed_receipt.
369
+ * Allows an operator to require signing for a capability the actor declared
370
+ * as unsigned (e.g. a compliance deployment that needs signed receipts for
371
+ * every action), or to suppress signing for a high-frequency capability
372
+ * the actor flagged as requiring it.
373
+ */
374
+ require_signed_receipt?: boolean;
375
+ /**
376
+ * OID of the parent grant when this grant was delegated from another actor.
377
+ * When present the gateway MUST verify the parent grant covers all
378
+ * capability_scopes in this grant before accepting it. Enables verifiable
379
+ * delegation chains (orchestrator -> sub-agent). max_delegation_depth caps
380
+ * how many hops this grant may be further delegated.
381
+ */
382
+ parent_grant_oid?: string;
383
+ /**
384
+ * Maximum number of additional delegation hops permitted below this grant.
385
+ * When absent from a grant covering any capability with physical_safety=true,
386
+ * the gateway MUST treat it as 0 (no sub-delegation). A gateway-enforced hard
387
+ * cap of 10 applies regardless of the value set here.
388
+ */
389
+ max_delegation_depth?: number;
390
+ /**
391
+ * For safety_class C without physical_safety: override for the default
392
+ * timestamp validation window in seconds. Gateway applies its default if absent.
393
+ */
394
+ timestamp_window_seconds?: number;
395
+ /**
396
+ * Additional seconds beyond grant expiry during which offline provisional
397
+ * receipts are accepted at reconciliation. Defaults to 0.
398
+ */
399
+ offline_grace_seconds?: number;
400
+ /**
401
+ * Maximum duration any device may use this grant without syncing to the
402
+ * gateway. After this window, further invocations MUST be denied until
403
+ * the device reconnects.
404
+ */
405
+ max_grant_offline_ttl_ms?: number;
406
+ /**
407
+ * Maximum acceptable age of a revocation bundle for this grant. Devices
408
+ * MUST deny physical_safety/class C invocations if the bundle is older
409
+ * than this value.
410
+ */
411
+ max_revocation_bundle_age_ms?: number;
412
+ /**
413
+ * When true, marks this grant as a break-glass grant. A break-glass grant
414
+ * pre-authorizes a defined set of emergency capabilities with an
415
+ * offline-verifiable signed token, for use when the gateway is unreachable
416
+ * and immediate action is required for safety or clinical reasons.
417
+ */
418
+ break_glass?: boolean;
419
+ /**
420
+ * TTL of the break-glass token in milliseconds from issuance.
421
+ * RECOMMENDED: 4 hours (14_400_000 ms). Required when break_glass is true.
422
+ */
423
+ break_glass_ttl_ms?: number;
424
+ /**
425
+ * Maximum invocations allowed under this token before it is exhausted.
426
+ * Defaults to 1 for safety_class C.
427
+ */
428
+ break_glass_max_invocations?: number;
429
+ /**
430
+ * When true, the invoker MUST supply a break_glass_reason string in
431
+ * invocation args when activating break-glass operation.
432
+ */
433
+ break_glass_requires_reason?: boolean;
434
+ /**
435
+ * Item 6 [DESIGN]: Compartment label for this grant. At invocation time,
436
+ * if the grant carries a compartment the invocation compartment MUST exactly
437
+ * match. Cross-compartment access requires a bridge grant issued through a
438
+ * TPI-gated HITL workflow.
439
+ */
440
+ compartment?: string;
441
+ }
442
+ export type CapabilityGrant = GapCdroEnvelope<CapabilityGrantBody>;
443
+ export interface CapabilityInvocationBody {
444
+ caller: {
445
+ actor_type: GapActorType;
446
+ actor_oid: string;
447
+ actor_session_id?: string;
448
+ grant_oid: string;
449
+ };
450
+ capability: string;
451
+ /**
452
+ * OID of the capability's declaration envelope. Optional routing hint --
453
+ * the gateway resolves it from the grant if omitted. When provided, the
454
+ * gateway MAY use it to skip the declaration lookup.
455
+ */
456
+ capability_declaration_oid?: string;
457
+ args: Record<string, unknown>;
458
+ workflow_context?: {
459
+ workflow_instance_oid: string;
460
+ stage_id: string;
461
+ };
462
+ sla_hint?: {
463
+ max_latency_ms?: number;
464
+ deferrable?: boolean;
465
+ };
466
+ idempotency_key?: string;
467
+ /**
468
+ * Server-stamped. Clients SHOULD omit this field; the gateway sets it to
469
+ * the time the invocation was received. If provided by the client, the
470
+ * value is accepted as-is but the gateway may override it.
471
+ */
472
+ invoked_at_ms?: number;
473
+ /**
474
+ * Unix epoch ms when the action originally occurred in the caller's reference
475
+ * frame (game-world time, clinical queue time, SCADA scan cycle). Populated
476
+ * by the client; not used for replay prevention. Stored in receipt for audit.
477
+ */
478
+ client_event_ms?: number;
479
+ /**
480
+ * Unix epoch ms when the invocation was enqueued for submission (e.g. at
481
+ * reconnect after an offline period). Optional; aids debugging of delivery
482
+ * latency.
483
+ */
484
+ queued_at_ms?: number;
485
+ /**
486
+ * Item 1 [DESIGN]: Delegation chain steps, when this invocation was reached
487
+ * through a multi-hop orchestration chain. Max 10 steps; gateway returns
488
+ * HTTP 400 'delegation_depth_exceeded' when length exceeds 10.
489
+ */
490
+ delegation_chain?: DelegationStep[];
491
+ /**
492
+ * Item 2 [DESIGN]: Raw MCP tool-call context when the capability was
493
+ * auto-generated from an MCP tools/list response. The gateway validates
494
+ * server_id is non-empty and tool_name does not start with 'gap:'.
495
+ */
496
+ mcp_tool_call?: McpToolCallContext;
497
+ /**
498
+ * Item 6 [DESIGN]: Compartment label on this invocation. MUST exactly match
499
+ * the grant's compartment when the grant carries one. The gateway MUST return
500
+ * HTTP 404 (not HTTP 403) when the invoking actor's compartment level is
501
+ * insufficient to know a resource exists.
502
+ */
503
+ compartment?: string;
504
+ }
505
+ export type CapabilityInvocation = GapCdroEnvelope<CapabilityInvocationBody>;
506
+ export interface KeyEntry {
507
+ key_id: string;
508
+ public_key_base64: string;
509
+ algorithm: 'Ed25519' | 'ML-DSA-65' | 'Ed25519+ML-DSA-65';
510
+ valid_from_ms: number;
511
+ expires_at_ms: number;
512
+ }
513
+ export interface KeyringExportBody {
514
+ keys: KeyEntry[];
515
+ exported_at_ms: number;
516
+ expires_at_ms: number;
517
+ }
518
+ export interface OfflinePolicy {
519
+ max_offline_duration_ms: number;
520
+ max_offline_invocations: number;
521
+ offline_capability_filter?: string[];
522
+ offline_allowed?: boolean;
523
+ }
524
+ export interface OfflineBundleBody {
525
+ grant: CapabilityGrant;
526
+ declaration: CapabilityDeclaration;
527
+ keyring: KeyringExportBody;
528
+ revocation_snapshot: RevocationSnapshotBody;
529
+ offline_policy: OfflinePolicy;
530
+ }
531
+ export interface RevocationEntry {
532
+ grant_oid: string;
533
+ effective_at_ms: number;
534
+ kind: 'immediate' | 'scheduled' | 'provisional_block';
535
+ }
536
+ export interface RevocationSnapshotBody {
537
+ revocations: RevocationEntry[];
538
+ snapshot_at_ms: number;
539
+ expires_at_ms: number;
540
+ tenant_id: string;
541
+ }
542
+ export interface BreakGlassTokenBody {
543
+ grant_oid: string;
544
+ actor_oid: string;
545
+ valid_from_ms: number;
546
+ expires_at_ms: number;
547
+ permitted_capabilities: string[];
548
+ max_invocations: number;
549
+ }
550
+ export interface LocalOverrideCredentialBody {
551
+ grant_oid: string;
552
+ actor_oid: string;
553
+ expires_at_ms: number;
554
+ single_use: true;
555
+ override_reason_required: boolean;
556
+ }
557
+ /**
558
+ * C16: Body of a gap:erasure_event CDRO. Replaces the body of the targeted
559
+ * receipt with a fixed erasure sentinel while preserving envelope metadata.
560
+ * The erasure event OID anchors to the original CDRO OID and is itself a
561
+ * signed CDRO, making it non-repudiable. Verifiers MUST treat an erasure event
562
+ * as authoritative over the prior OID body.
563
+ */
564
+ export interface ErasureEventBody {
565
+ /** OID of the CDRO being erased. */
566
+ target_oid: string;
567
+ /** Reason code for the erasure. */
568
+ erasure_reason: 'gdpr_article_17' | 'ccpa' | 'operator_policy';
569
+ /** Unix epoch ms of erasure. */
570
+ erased_at_ms: number;
571
+ /** Actor OID issuing the erasure. */
572
+ erased_by: string;
573
+ /** Array of field paths erased from the target CDRO body. */
574
+ fields_erased: string[];
575
+ }
576
+ /**
577
+ * C12: Body of a gap:lca_root CDRO. Bootstraps a Local Credential Authority
578
+ * for deployments without external connectivity or without a SynOI-operated
579
+ * token issuer. The LCA root is signed by the local root key; actor credentials
580
+ * are then issued by the LCA and verified using the locally-held LCA public key.
581
+ */
582
+ export interface LcaRootBody {
583
+ root_public_key_base64: string;
584
+ algorithm: 'ML-DSA-65' | 'Ed25519';
585
+ tenant_id: string;
586
+ valid_from_ms: number;
587
+ expires_at_ms: number;
588
+ }
589
+ /**
590
+ * Match a capability `target` against a `pattern`.
591
+ *
592
+ * Rules (matching the GAP gateway reference implementation):
593
+ * - Exact string match returns true.
594
+ * - A pattern ending in `*` matches any target with the prefix before `*`.
595
+ * - Everything else returns false.
596
+ *
597
+ * Examples:
598
+ * capabilityMatches('skill.create', 'skill.create') // true
599
+ * capabilityMatches('skill.*', 'skill.create') // true
600
+ * capabilityMatches('skill.*', 'skill.update') // true
601
+ * capabilityMatches('skill.create', 'skill.update') // false
602
+ * capabilityMatches('*', 'anything') // true
603
+ */
604
+ export declare function capabilityMatches(pattern: string, target: string): boolean;
605
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * capabilities.ts -- Declaration / Grant / Invocation shapes.
3
+ *
4
+ * These mirror the GAP gateway reference implementation wire types.
5
+ * The trio is the GAP operational core:
6
+ *
7
+ * - CapabilityDeclaration: an actor announces "I can do X under conditions Y".
8
+ * - CapabilityGrant: an operator says "actor A may invoke X within scope S until time T".
9
+ * - CapabilityInvocation: an actor performs "I am invoking X, here are my args + the grant I'm using".
10
+ *
11
+ * Every gate check (grant exists + not revoked + not expired + scope matches
12
+ * + preconditions hold) happens on invocation. The decision becomes a
13
+ * GapDecisionReceipt.
14
+ */
15
+ // -- Capability pattern matching ----------------------------------------------
16
+ /**
17
+ * Match a capability `target` against a `pattern`.
18
+ *
19
+ * Rules (matching the GAP gateway reference implementation):
20
+ * - Exact string match returns true.
21
+ * - A pattern ending in `*` matches any target with the prefix before `*`.
22
+ * - Everything else returns false.
23
+ *
24
+ * Examples:
25
+ * capabilityMatches('skill.create', 'skill.create') // true
26
+ * capabilityMatches('skill.*', 'skill.create') // true
27
+ * capabilityMatches('skill.*', 'skill.update') // true
28
+ * capabilityMatches('skill.create', 'skill.update') // false
29
+ * capabilityMatches('*', 'anything') // true
30
+ */
31
+ export function capabilityMatches(pattern, target) {
32
+ if (pattern === target)
33
+ return true;
34
+ if (pattern === '*')
35
+ return true; // match-all
36
+ // M-8: Two wildcard levels.
37
+ // 'prefix.**' matches all descendants recursively (the prefix itself OR any
38
+ // path under it). Must be checked before '.*' because '.**' ends with '.*'.
39
+ if (pattern.endsWith('.**')) {
40
+ const prefix = pattern.slice(0, -3); // strip '.**'
41
+ return target === prefix || target.startsWith(prefix + '.');
42
+ }
43
+ // Segment-boundary wildcard: 'skill.*' matches 'skill.create' (direct
44
+ // children only -- single path segment). A non-boundary pattern like
45
+ // 'admin.us*' must NOT prefix-match 'admin.users.delete' (privilege-
46
+ // escalation footgun). The '*' must follow a '.'.
47
+ if (pattern.endsWith('.*')) {
48
+ const prefix = pattern.slice(0, -1); // keep the trailing '.', e.g. 'skill.'
49
+ return target.startsWith(prefix);
50
+ }
51
+ return false;
52
+ }
53
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAqpBH,gFAAgF;AAEhF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAc;IAC/D,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IACnC,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA,CAAG,YAAY;IAC/C,4BAA4B;IAC5B,4EAA4E;IAC5E,4EAA4E;IAC5E,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA,CAAE,cAAc;QACnD,OAAO,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,CAAA;IAC7D,CAAC;IACD,sEAAsE;IACtE,qEAAqE;IACrE,qEAAqE;IACrE,kDAAkD;IAClD,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA,CAAG,uCAAuC;QAC7E,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}