@cotal-ai/core 0.11.6 → 0.13.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 (170) hide show
  1. package/dist/acls.d.ts +31 -7
  2. package/dist/acls.d.ts.map +1 -1
  3. package/dist/acls.js +105 -17
  4. package/dist/acls.js.map +1 -1
  5. package/dist/agent-file.js +1 -1
  6. package/dist/agent-file.js.map +1 -1
  7. package/dist/auth-provider.d.ts +90 -10
  8. package/dist/auth-provider.d.ts.map +1 -1
  9. package/dist/auth-provider.js.map +1 -1
  10. package/dist/backup-config.d.ts +55 -0
  11. package/dist/backup-config.d.ts.map +1 -0
  12. package/dist/backup-config.js +243 -0
  13. package/dist/backup-config.js.map +1 -0
  14. package/dist/backup.d.ts +86 -0
  15. package/dist/backup.d.ts.map +1 -0
  16. package/dist/backup.js +497 -0
  17. package/dist/backup.js.map +1 -0
  18. package/dist/broker-floor.d.ts +34 -0
  19. package/dist/broker-floor.d.ts.map +1 -0
  20. package/dist/broker-floor.js +39 -0
  21. package/dist/broker-floor.js.map +1 -0
  22. package/dist/canonical.d.ts +24 -0
  23. package/dist/canonical.d.ts.map +1 -0
  24. package/dist/canonical.js +159 -0
  25. package/dist/canonical.js.map +1 -0
  26. package/dist/channels.d.ts.map +1 -1
  27. package/dist/channels.js +8 -1
  28. package/dist/channels.js.map +1 -1
  29. package/dist/connector.d.ts +4 -0
  30. package/dist/connector.d.ts.map +1 -1
  31. package/dist/endpoint-action.d.ts +424 -0
  32. package/dist/endpoint-action.d.ts.map +1 -0
  33. package/dist/endpoint-action.js +910 -0
  34. package/dist/endpoint-action.js.map +1 -0
  35. package/dist/endpoint-binding.d.ts +344 -0
  36. package/dist/endpoint-binding.d.ts.map +1 -0
  37. package/dist/endpoint-binding.js +753 -0
  38. package/dist/endpoint-binding.js.map +1 -0
  39. package/dist/endpoint-checkpoint.d.ts +292 -0
  40. package/dist/endpoint-checkpoint.d.ts.map +1 -0
  41. package/dist/endpoint-checkpoint.js +818 -0
  42. package/dist/endpoint-checkpoint.js.map +1 -0
  43. package/dist/endpoint-cluster.d.ts +95 -0
  44. package/dist/endpoint-cluster.d.ts.map +1 -0
  45. package/dist/endpoint-cluster.js +194 -0
  46. package/dist/endpoint-cluster.js.map +1 -0
  47. package/dist/endpoint-contract-store.d.ts +90 -0
  48. package/dist/endpoint-contract-store.d.ts.map +1 -0
  49. package/dist/endpoint-contract-store.js +348 -0
  50. package/dist/endpoint-contract-store.js.map +1 -0
  51. package/dist/endpoint-envelope.d.ts +165 -0
  52. package/dist/endpoint-envelope.d.ts.map +1 -0
  53. package/dist/endpoint-envelope.js +346 -0
  54. package/dist/endpoint-envelope.js.map +1 -0
  55. package/dist/endpoint-grants.d.ts +123 -0
  56. package/dist/endpoint-grants.d.ts.map +1 -0
  57. package/dist/endpoint-grants.js +215 -0
  58. package/dist/endpoint-grants.js.map +1 -0
  59. package/dist/endpoint-guard.d.ts +222 -0
  60. package/dist/endpoint-guard.d.ts.map +1 -0
  61. package/dist/endpoint-guard.js +468 -0
  62. package/dist/endpoint-guard.js.map +1 -0
  63. package/dist/endpoint-handle.d.ts +176 -0
  64. package/dist/endpoint-handle.d.ts.map +1 -0
  65. package/dist/endpoint-handle.js +608 -0
  66. package/dist/endpoint-handle.js.map +1 -0
  67. package/dist/endpoint-journal.d.ts +225 -0
  68. package/dist/endpoint-journal.d.ts.map +1 -0
  69. package/dist/endpoint-journal.js +431 -0
  70. package/dist/endpoint-journal.js.map +1 -0
  71. package/dist/endpoint-receipt.d.ts +225 -0
  72. package/dist/endpoint-receipt.d.ts.map +1 -0
  73. package/dist/endpoint-receipt.js +417 -0
  74. package/dist/endpoint-receipt.js.map +1 -0
  75. package/dist/endpoint-records.d.ts +243 -0
  76. package/dist/endpoint-records.d.ts.map +1 -0
  77. package/dist/endpoint-records.js +591 -0
  78. package/dist/endpoint-records.js.map +1 -0
  79. package/dist/endpoint-serve.d.ts +176 -0
  80. package/dist/endpoint-serve.d.ts.map +1 -0
  81. package/dist/endpoint-serve.js +446 -0
  82. package/dist/endpoint-serve.js.map +1 -0
  83. package/dist/endpoint-service.d.ts +518 -0
  84. package/dist/endpoint-service.d.ts.map +1 -0
  85. package/dist/endpoint-service.js +973 -0
  86. package/dist/endpoint-service.js.map +1 -0
  87. package/dist/endpoint-session.d.ts +398 -0
  88. package/dist/endpoint-session.d.ts.map +1 -0
  89. package/dist/endpoint-session.js +834 -0
  90. package/dist/endpoint-session.js.map +1 -0
  91. package/dist/endpoint-signing.d.ts +105 -0
  92. package/dist/endpoint-signing.d.ts.map +1 -0
  93. package/dist/endpoint-signing.js +190 -0
  94. package/dist/endpoint-signing.js.map +1 -0
  95. package/dist/endpoint-subjects.d.ts +222 -0
  96. package/dist/endpoint-subjects.d.ts.map +1 -0
  97. package/dist/endpoint-subjects.js +381 -0
  98. package/dist/endpoint-subjects.js.map +1 -0
  99. package/dist/endpoint-supervisor.d.ts +19 -0
  100. package/dist/endpoint-supervisor.d.ts.map +1 -0
  101. package/dist/endpoint-supervisor.js +12 -0
  102. package/dist/endpoint-supervisor.js.map +1 -0
  103. package/dist/endpoint-traits.d.ts +225 -0
  104. package/dist/endpoint-traits.d.ts.map +1 -0
  105. package/dist/endpoint-traits.js +469 -0
  106. package/dist/endpoint-traits.js.map +1 -0
  107. package/dist/endpoint-verbs.d.ts +277 -0
  108. package/dist/endpoint-verbs.d.ts.map +1 -0
  109. package/dist/endpoint-verbs.js +576 -0
  110. package/dist/endpoint-verbs.js.map +1 -0
  111. package/dist/endpoint-virtual.d.ts +308 -0
  112. package/dist/endpoint-virtual.d.ts.map +1 -0
  113. package/dist/endpoint-virtual.js +440 -0
  114. package/dist/endpoint-virtual.js.map +1 -0
  115. package/dist/endpoint-work.d.ts +304 -0
  116. package/dist/endpoint-work.d.ts.map +1 -0
  117. package/dist/endpoint-work.js +728 -0
  118. package/dist/endpoint-work.js.map +1 -0
  119. package/dist/endpoint.d.ts +66 -22
  120. package/dist/endpoint.d.ts.map +1 -1
  121. package/dist/endpoint.js +289 -89
  122. package/dist/endpoint.js.map +1 -1
  123. package/dist/evict.d.ts +95 -32
  124. package/dist/evict.d.ts.map +1 -1
  125. package/dist/evict.js +193 -3
  126. package/dist/evict.js.map +1 -1
  127. package/dist/index.d.ts +29 -0
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +29 -0
  130. package/dist/index.js.map +1 -1
  131. package/dist/lease.d.ts +4 -0
  132. package/dist/lease.d.ts.map +1 -1
  133. package/dist/lease.js.map +1 -1
  134. package/dist/members.d.ts +4 -4
  135. package/dist/members.d.ts.map +1 -1
  136. package/dist/members.js +12 -12
  137. package/dist/members.js.map +1 -1
  138. package/dist/provision.d.ts +78 -20
  139. package/dist/provision.d.ts.map +1 -1
  140. package/dist/provision.js +214 -37
  141. package/dist/provision.js.map +1 -1
  142. package/dist/runtime.d.ts +3 -0
  143. package/dist/runtime.d.ts.map +1 -1
  144. package/dist/safe-pattern.d.ts +33 -0
  145. package/dist/safe-pattern.d.ts.map +1 -0
  146. package/dist/safe-pattern.js +486 -0
  147. package/dist/safe-pattern.js.map +1 -0
  148. package/dist/schema-profile.d.ts +93 -0
  149. package/dist/schema-profile.d.ts.map +1 -0
  150. package/dist/schema-profile.js +284 -0
  151. package/dist/schema-profile.js.map +1 -0
  152. package/dist/secret-store.d.ts +46 -0
  153. package/dist/secret-store.d.ts.map +1 -0
  154. package/dist/secret-store.js +2 -0
  155. package/dist/secret-store.js.map +1 -0
  156. package/dist/space-auth.d.ts +9 -0
  157. package/dist/space-auth.d.ts.map +1 -0
  158. package/dist/space-auth.js +126 -0
  159. package/dist/space-auth.js.map +1 -0
  160. package/dist/streams.d.ts +14 -10
  161. package/dist/streams.d.ts.map +1 -1
  162. package/dist/streams.js +47 -76
  163. package/dist/streams.js.map +1 -1
  164. package/dist/subjects.d.ts +100 -40
  165. package/dist/subjects.d.ts.map +1 -1
  166. package/dist/subjects.js +136 -60
  167. package/dist/subjects.js.map +1 -1
  168. package/dist/types.d.ts +9 -0
  169. package/dist/types.d.ts.map +1 -1
  170. package/package.json +6 -2
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The normative JSON Schema 2020-12 execution profile for contract schemas (SPEC §13.7, D27).
3
+ *
4
+ * A contract schema is a CLOSED resource bundle: fully self-contained (local `#/…` refs) or
5
+ * referencing other contract-store artifacts by digest (`cotal:sha256:<hex>`) only. Ambient
6
+ * HTTP/file/URI resolution never happens; every external reference must be supplied by the
7
+ * caller as an already-fetched, digest-verified bundle member. Registration-time violations are
8
+ * `contract-invalid` (distinct from invocation-time `bad-request`), and all bounds are enforced
9
+ * BEFORE compilation so a hostile descriptor cannot turn registration into a DoS.
10
+ */
11
+ import { type ValidateFunction } from "ajv/dist/2020.js";
12
+ /** Registration-time bounds (SPEC §13.7/§13.8). Fixed by the profile, not caller-tunable, and
13
+ * RUNTIME-frozen (the afa715b class): a post-import `maxDepth = MAX_SAFE_INTEGER` would remove
14
+ * the pre-compilation recursion/DoS ceiling, so mutation throws instead. */
15
+ export declare const SCHEMA_PROFILE: Readonly<{
16
+ /** One schema document's canonical form, bytes. */
17
+ readonly maxDocumentBytes: number;
18
+ /** The complete resolved closure (root + digest-referenced members), bytes. */
19
+ readonly maxClosureBytes: number;
20
+ /** Structural nesting depth of any document. */
21
+ readonly maxDepth: 32;
22
+ /** Digest-reference chain depth (root → member → member …). */
23
+ readonly maxRefChain: 32;
24
+ /** Compile budget per closure, ms. */
25
+ readonly compileBudgetMs: 100;
26
+ /** Bounded pattern complexity: max characters of any `pattern` / `patternProperties` regex. */
27
+ readonly maxPatternChars: 256;
28
+ /** Per-value validation budget at the serving boundary, ms (§13.8 reference; post-hoc,
29
+ * fail-loud as `bad-request`). */
30
+ readonly validateBudgetMs: 10;
31
+ /** Compiled-schema cache entries (the SPEC's reference 256-entry LRU). */
32
+ readonly compiledCacheEntries: 256;
33
+ }>;
34
+ /** The canonical void schema (§13.7): the one artifact a side with no payload declares, so both
35
+ * `op` digests exist for every command. Validation against it means the payload is absent or
36
+ * `null`. */
37
+ export declare const VOID_SCHEMA: Readonly<{
38
+ readonly type: "null";
39
+ }>;
40
+ /** Artifact digest of the void schema document — one fixed value by construction. */
41
+ export declare const VOID_SCHEMA_ARTIFACT_DIGEST: string;
42
+ /** The void schema's CLOSURE digest (the §13.7 manifest of a self-contained document) — the
43
+ * value `op.inputDigest`/`op.outputDigest` carry for a payload-free side. */
44
+ export declare const VOID_SCHEMA_DIGEST: string;
45
+ /** Thrown for every profile violation at registration/ingest time; maps to the wire error
46
+ * code `contract-invalid` (never `bad-request`, which is for invocation-time args). */
47
+ export declare class ContractInvalidError extends Error {
48
+ readonly code: "contract-invalid";
49
+ constructor(message: string);
50
+ }
51
+ /** A closed schema bundle: the root document plus every digest-referenced member, already
52
+ * fetched and digest-verified (see `verifyArtifact`). Keyed by `sha256:<hex>`. */
53
+ export interface SchemaBundle {
54
+ root: unknown;
55
+ /** Digest → verified member document. Every `cotal:` ref in the closure must resolve here. */
56
+ members?: Record<string, unknown>;
57
+ }
58
+ /** A registered contract schema: the compiled validator plus the bundle's CLOSURE digest —
59
+ * the artifact digest of the §13.7 manifest `{ v: 1, root, members[] }` (members = every
60
+ * artifact transitively REACHABLE from the root, sorted and deduplicated). The closure digest
61
+ * is the contract identity `op.inputDigest`/`op.outputDigest` pin.
62
+ *
63
+ * The interface is structural for CONSUMERS, but authority seams never accept structure: a
64
+ * compiled contract is FROZEN and brand-registered by this compiler ({@link compileContract}),
65
+ * and {@link assertCompiledContract} refuses any object the profile compiler did not produce —
66
+ * so a hand-built `{validate, closureDigest}` pair (an arbitrary validator wearing a
67
+ * registered digest) can never enter a serve table (§13.7: the digest and its enforcing
68
+ * validator are one value). */
69
+ export interface CompiledContract {
70
+ validate: ValidateFunction;
71
+ closureDigest: string;
72
+ }
73
+ /** True iff `c` is a frozen contract this profile compiler produced (never structural). */
74
+ export declare function isCompiledContract(c: unknown): c is CompiledContract;
75
+ /** Refuse anything that is not a compiler-produced contract: authority seams (the serve table,
76
+ * the grant mint) call this so a fabricated validator/digest pair fails loud, never serves. */
77
+ export declare function assertCompiledContract(c: unknown, what: string): CompiledContract;
78
+ /** Validate the whole closure against the profile and compile it with a real 2020-12
79
+ * validator. No network, no filesystem: `loadSchema` is never installed, and every
80
+ * `cotal:` reference must be present in `bundle.members`. */
81
+ export declare function compileContract(bundle: SchemaBundle): CompiledContract;
82
+ /** {@link compileContract} without the closure identity, kept for validation-only callers. */
83
+ export declare function compileContractSchema(bundle: SchemaBundle): ValidateFunction;
84
+ /** A bounded compiled-schema LRU (SPEC §13.7's reference 256-entry cache), keyed by CLOSURE
85
+ * digest. The profile walk (incl. member digest verification) runs on EVERY call — only the
86
+ * ajv compilation is skipped on a hit. Sound across callers: two bundles with one closure
87
+ * digest are byte-identical closures, so a hit can never serve another caller's
88
+ * mis-assembled bundle. */
89
+ export declare function createCompiledContractCache(capacity?: number): {
90
+ compile: (bundle: SchemaBundle) => CompiledContract;
91
+ size: () => number;
92
+ };
93
+ //# sourceMappingURL=schema-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-profile.d.ts","sourceRoot":"","sources":["../src/schema-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAIlE;;6EAE6E;AAC7E,eAAO,MAAM,cAAc;IACzB,mDAAmD;;IAEnD,+EAA+E;;IAE/E,gDAAgD;;IAEhD,+DAA+D;;IAE/D,sCAAsC;;IAEtC,+FAA+F;;IAE/F;uCACmC;;IAEnC,0EAA0E;;EAEjE,CAAC;AAEZ;;cAEc;AACd,eAAO,MAAM,WAAW;;EAA2C,CAAC;AACpE,qFAAqF;AACrF,eAAO,MAAM,2BAA2B,QAA8B,CAAC;AACvE;8EAC8E;AAC9E,eAAO,MAAM,kBAAkB,QAA2E,CAAC;AAK3G;wFACwF;AACxF,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAG,kBAAkB,CAAU;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAqED;mFACmF;AACnF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAqBD;;;;;;;;;;gCAUgC;AAChC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAaD,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,gBAAgB,CAEpE;AAED;gGACgG;AAChG,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAIjF;AA4ED;;8DAE8D;AAC9D,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAGtE;AAED,8FAA8F;AAC9F,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAE5E;AAED;;;;4BAI4B;AAC5B,wBAAgB,2BAA2B,CAAC,QAAQ,GAAE,MAA4C,GAAG;IACnG,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,gBAAgB,CAAC;IACpD,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB,CAmBA"}
@@ -0,0 +1,284 @@
1
+ /**
2
+ * The normative JSON Schema 2020-12 execution profile for contract schemas (SPEC §13.7, D27).
3
+ *
4
+ * A contract schema is a CLOSED resource bundle: fully self-contained (local `#/…` refs) or
5
+ * referencing other contract-store artifacts by digest (`cotal:sha256:<hex>`) only. Ambient
6
+ * HTTP/file/URI resolution never happens; every external reference must be supplied by the
7
+ * caller as an already-fetched, digest-verified bundle member. Registration-time violations are
8
+ * `contract-invalid` (distinct from invocation-time `bad-request`), and all bounds are enforced
9
+ * BEFORE compilation so a hostile descriptor cannot turn registration into a DoS.
10
+ */
11
+ import { Ajv2020 } from "ajv/dist/2020.js";
12
+ import { canonicalJson, contractDigest, isContractDigest } from "./canonical.js";
13
+ import { assertSafePattern } from "./safe-pattern.js";
14
+ /** Registration-time bounds (SPEC §13.7/§13.8). Fixed by the profile, not caller-tunable, and
15
+ * RUNTIME-frozen (the afa715b class): a post-import `maxDepth = MAX_SAFE_INTEGER` would remove
16
+ * the pre-compilation recursion/DoS ceiling, so mutation throws instead. */
17
+ export const SCHEMA_PROFILE = Object.freeze({
18
+ /** One schema document's canonical form, bytes. */
19
+ maxDocumentBytes: 256 * 1024,
20
+ /** The complete resolved closure (root + digest-referenced members), bytes. */
21
+ maxClosureBytes: 1024 * 1024,
22
+ /** Structural nesting depth of any document. */
23
+ maxDepth: 32,
24
+ /** Digest-reference chain depth (root → member → member …). */
25
+ maxRefChain: 32,
26
+ /** Compile budget per closure, ms. */
27
+ compileBudgetMs: 100,
28
+ /** Bounded pattern complexity: max characters of any `pattern` / `patternProperties` regex. */
29
+ maxPatternChars: 256,
30
+ /** Per-value validation budget at the serving boundary, ms (§13.8 reference; post-hoc,
31
+ * fail-loud as `bad-request`). */
32
+ validateBudgetMs: 10,
33
+ /** Compiled-schema cache entries (the SPEC's reference 256-entry LRU). */
34
+ compiledCacheEntries: 256,
35
+ });
36
+ /** The canonical void schema (§13.7): the one artifact a side with no payload declares, so both
37
+ * `op` digests exist for every command. Validation against it means the payload is absent or
38
+ * `null`. */
39
+ export const VOID_SCHEMA = Object.freeze({ type: "null" });
40
+ /** Artifact digest of the void schema document — one fixed value by construction. */
41
+ export const VOID_SCHEMA_ARTIFACT_DIGEST = contractDigest(VOID_SCHEMA);
42
+ /** The void schema's CLOSURE digest (the §13.7 manifest of a self-contained document) — the
43
+ * value `op.inputDigest`/`op.outputDigest` carry for a payload-free side. */
44
+ export const VOID_SCHEMA_DIGEST = contractDigest({ v: 1, root: VOID_SCHEMA_ARTIFACT_DIGEST, members: [] });
45
+ /** The digest-pinned contract-store reference scheme: `cotal:sha256:<hex>[#/json/pointer]`. */
46
+ const STORE_REF = /^cotal:(sha256:[0-9a-f]{64})(#.*)?$/;
47
+ /** Thrown for every profile violation at registration/ingest time; maps to the wire error
48
+ * code `contract-invalid` (never `bad-request`, which is for invocation-time args). */
49
+ export class ContractInvalidError extends Error {
50
+ code = "contract-invalid";
51
+ constructor(message) {
52
+ super(message);
53
+ this.name = "ContractInvalidError";
54
+ }
55
+ }
56
+ /** Canonicalize within the profile boundary: an I-JSON violation (lone surrogate, undefined,
57
+ * non-finite number) in a schema document is a PROFILE violation and must surface as
58
+ * `contract-invalid`, never as a raw canonicalizer error (§13.7). */
59
+ function canonicalOrInvalid(v, label) {
60
+ try {
61
+ return canonicalJson(v);
62
+ }
63
+ catch (e) {
64
+ throw new ContractInvalidError(`${label}: ${e.message}`);
65
+ }
66
+ }
67
+ function digestOrInvalid(v, label) {
68
+ try {
69
+ return contractDigest(v);
70
+ }
71
+ catch (e) {
72
+ throw new ContractInvalidError(`${label}: ${e.message}`);
73
+ }
74
+ }
75
+ function structuralDepth(v, depth = 0) {
76
+ if (depth > SCHEMA_PROFILE.maxDepth)
77
+ return depth; // short-circuit, caller throws
78
+ if (v === null || typeof v !== "object")
79
+ return depth;
80
+ let max = depth;
81
+ const children = Array.isArray(v) ? v : Object.values(v);
82
+ for (const c of children) {
83
+ const d = structuralDepth(c, depth + 1);
84
+ if (d > max)
85
+ max = d;
86
+ if (max > SCHEMA_PROFILE.maxDepth)
87
+ return max;
88
+ }
89
+ return max;
90
+ }
91
+ /** The bounded-pattern-complexity gate (§13.7/§13.8 "bounded pattern complexity", "bounded
92
+ * regex"): the {@link assertSafePattern} SAFE SUBSET — a length bound plus an admission
93
+ * analysis that refuses nested repetition, repeated nullable or ambiguous-alternation bodies,
94
+ * overlapping variable repetitions in sequence, backreferences, lookarounds, and anything it
95
+ * cannot parse. Conservative by construction: uncertainty refuses. A refused pattern is
96
+ * rewritten by its author at registration time (`contract-invalid`), never probed at
97
+ * validation time — the post-hoc validate budget can only classify a stall, not prevent it. */
98
+ function assertBoundedPattern(p, label, where) {
99
+ try {
100
+ assertSafePattern(p, SCHEMA_PROFILE.maxPatternChars);
101
+ }
102
+ catch (e) {
103
+ throw new ContractInvalidError(`${label}: ${where} refused: ${e.message}`);
104
+ }
105
+ }
106
+ /** Collect every `$ref` string in a schema document and gate its regex patterns (structural
107
+ * walk; `$ref` in 2020-12 is always a string-valued keyword wherever it appears; `pattern`
108
+ * values and `patternProperties` keys are the profile's bounded-pattern-complexity surface). */
109
+ function collectRefs(v, label, out = []) {
110
+ if (v === null || typeof v !== "object")
111
+ return out;
112
+ if (Array.isArray(v)) {
113
+ for (const c of v)
114
+ collectRefs(c, label, out);
115
+ return out;
116
+ }
117
+ for (const [k, c] of Object.entries(v)) {
118
+ if ((k === "$ref" || k === "$dynamicRef") && typeof c === "string")
119
+ out.push(c);
120
+ if (k === "pattern" && typeof c === "string")
121
+ assertBoundedPattern(c, label, "a pattern");
122
+ if (k === "patternProperties" && c !== null && typeof c === "object" && !Array.isArray(c)) {
123
+ for (const p of Object.keys(c))
124
+ assertBoundedPattern(p, label, "a patternProperties key");
125
+ }
126
+ collectRefs(c, label, out);
127
+ }
128
+ return out;
129
+ }
130
+ /** Enforce the D27 profile on one document: size, depth, and reference closure. Returns the
131
+ * digest-refs the document makes (for closure walking). */
132
+ function assertDocumentProfile(doc, label) {
133
+ const canonical = canonicalOrInvalid(doc, label); // also enforces I-JSON, as contract-invalid
134
+ const bytes = Buffer.byteLength(canonical, "utf8");
135
+ if (bytes > SCHEMA_PROFILE.maxDocumentBytes)
136
+ throw new ContractInvalidError(`${label}: document is ${bytes} bytes (profile max ${SCHEMA_PROFILE.maxDocumentBytes})`);
137
+ if (structuralDepth(doc) > SCHEMA_PROFILE.maxDepth)
138
+ throw new ContractInvalidError(`${label}: nesting exceeds profile depth ${SCHEMA_PROFILE.maxDepth}`);
139
+ const storeRefs = [];
140
+ for (const ref of collectRefs(doc, label)) {
141
+ if (ref.startsWith("#"))
142
+ continue; // local pointer/anchor — resolved within the document
143
+ const m = STORE_REF.exec(ref);
144
+ if (!m)
145
+ throw new ContractInvalidError(`${label}: external $ref ${JSON.stringify(ref)}; only local '#…' or digest-pinned 'cotal:sha256:<hex>' references are permitted (no ambient resolution)`);
146
+ storeRefs.push(m[1]);
147
+ }
148
+ return storeRefs;
149
+ }
150
+ /** Provenance brand: exactly the frozen objects this compiler returned. A WeakSet (not a
151
+ * field) so the brand is unforgeable and unserializable; the freeze makes field swaps on a
152
+ * branded object impossible, so brand membership proves BOTH fields came out of one compile. */
153
+ const COMPILED = new WeakSet();
154
+ function makeCompiled(validate, closureDigest) {
155
+ const compiled = Object.freeze({ validate, closureDigest });
156
+ COMPILED.add(compiled);
157
+ return compiled;
158
+ }
159
+ /** True iff `c` is a frozen contract this profile compiler produced (never structural). */
160
+ export function isCompiledContract(c) {
161
+ return typeof c === "object" && c !== null && COMPILED.has(c);
162
+ }
163
+ /** Refuse anything that is not a compiler-produced contract: authority seams (the serve table,
164
+ * the grant mint) call this so a fabricated validator/digest pair fails loud, never serves. */
165
+ export function assertCompiledContract(c, what) {
166
+ if (!isCompiledContract(c))
167
+ throw new ContractInvalidError(`${what} is not a profile-compiled contract (schema-profile compileContract); a structural {validate, closureDigest} pair carries no compile provenance and is refused (SPEC 13.7)`);
168
+ return c;
169
+ }
170
+ /** Enforce the profile on the whole closure WITHOUT compiling: bounds every document, walks the
171
+ * digest-reference graph breadth-first (chain depth + total size), VERIFIES every reachable
172
+ * member against its digest key (fail-loud `contract-invalid`, so a mis-assembled bundle can
173
+ * neither register nor poison the compiled cache), and returns the closure identity — the
174
+ * §13.7 manifest digest. */
175
+ function assertClosureProfile(bundle) {
176
+ const members = bundle.members ?? {};
177
+ for (const d of Object.keys(members)) {
178
+ if (!isContractDigest(d))
179
+ throw new ContractInvalidError(`bundle member key ${JSON.stringify(d)} is not a sha256 digest`);
180
+ }
181
+ const seen = new Set();
182
+ let closureBytes = 0;
183
+ let frontier = assertDocumentProfile(bundle.root, "root schema");
184
+ closureBytes += Buffer.byteLength(canonicalOrInvalid(bundle.root, "root schema"), "utf8");
185
+ for (let chain = 0; frontier.length > 0; chain++) {
186
+ if (chain >= SCHEMA_PROFILE.maxRefChain)
187
+ throw new ContractInvalidError(`reference chain exceeds profile depth ${SCHEMA_PROFILE.maxRefChain}`);
188
+ const next = [];
189
+ for (const digest of frontier) {
190
+ if (seen.has(digest))
191
+ continue;
192
+ seen.add(digest);
193
+ const member = members[digest];
194
+ if (member === undefined)
195
+ throw new ContractInvalidError(`unresolved digest reference ${digest}: not present in the bundle (schemas are closed; nothing is fetched)`);
196
+ if (digestOrInvalid(member, `member ${digest}`) !== digest)
197
+ throw new ContractInvalidError(`bundle member under ${digest} does not hash to its key (content is ${digestOrInvalid(member, `member ${digest}`)})`);
198
+ closureBytes += Buffer.byteLength(canonicalOrInvalid(member, `member ${digest}`), "utf8");
199
+ if (closureBytes > SCHEMA_PROFILE.maxClosureBytes)
200
+ throw new ContractInvalidError(`closure is ${closureBytes} bytes (profile max ${SCHEMA_PROFILE.maxClosureBytes})`);
201
+ next.push(...assertDocumentProfile(member, `member ${digest}`));
202
+ }
203
+ frontier = next;
204
+ }
205
+ // A closed bundle lists EXACTLY the closure: a member unreachable from the root escaped every
206
+ // bound and digest check above and never enters the closure identity, so accepting it would
207
+ // make registration history-dependent (cold compile vs cache hit) and hand unverified,
208
+ // unbounded input to the compiler. Refused deterministically, before hit and miss alike.
209
+ const extras = Object.keys(members).filter((d) => !seen.has(d));
210
+ if (extras.length > 0)
211
+ throw new ContractInvalidError(`bundle carries ${extras.length} member(s) unreachable from the root (${extras.slice(0, 3).join(", ")}${extras.length > 3 ? ", …" : ""})`);
212
+ return contractDigest({ v: 1, root: digestOrInvalid(bundle.root, "root schema"), members: [...seen].sort() });
213
+ }
214
+ function compileWithinBudget(bundle) {
215
+ const started = Date.now();
216
+ // Compile with deterministic local resolution only. Members register under their cotal: URI
217
+ // so in-document `$ref: "cotal:sha256:…"` resolves from the bundle, never the network.
218
+ const ajv = new Ajv2020({
219
+ strict: false, // the wire accepts full 2020-12, not ajv's strict-mode dialect subset
220
+ allErrors: false,
221
+ validateFormats: false,
222
+ loadSchema: undefined,
223
+ // PINNED, never inherited from Ajv's default: the safe-pattern analyzer models `/u`
224
+ // semantics exactly (astral atoms, surrogate refusals), so the engine MUST compile
225
+ // `pattern` with the `u` flag. If this ever flipped, patterns would be proven under one
226
+ // grammar and executed under another (an admitting under-approximation).
227
+ unicodeRegExp: true,
228
+ });
229
+ let validate;
230
+ try {
231
+ // Every member is reachable and digest-verified (assertClosureProfile refuses extras), so
232
+ // exactly the closure registers. A registration failure (e.g. a `$id` collision between
233
+ // members) is a profile rejection, same as a compile failure.
234
+ for (const [digest, member] of Object.entries(bundle.members ?? {}))
235
+ ajv.addSchema(member, `cotal:${digest}`);
236
+ validate = ajv.compile(bundle.root);
237
+ }
238
+ catch (e) {
239
+ throw new ContractInvalidError(`schema does not compile under the 2020-12 profile: ${e.message}`);
240
+ }
241
+ const elapsed = Date.now() - started;
242
+ if (elapsed > SCHEMA_PROFILE.compileBudgetMs)
243
+ throw new ContractInvalidError(`compile took ${elapsed}ms (profile budget ${SCHEMA_PROFILE.compileBudgetMs}ms)`);
244
+ return validate;
245
+ }
246
+ /** Validate the whole closure against the profile and compile it with a real 2020-12
247
+ * validator. No network, no filesystem: `loadSchema` is never installed, and every
248
+ * `cotal:` reference must be present in `bundle.members`. */
249
+ export function compileContract(bundle) {
250
+ const closureDigest = assertClosureProfile(bundle);
251
+ return makeCompiled(compileWithinBudget(bundle), closureDigest);
252
+ }
253
+ /** {@link compileContract} without the closure identity, kept for validation-only callers. */
254
+ export function compileContractSchema(bundle) {
255
+ return compileContract(bundle).validate;
256
+ }
257
+ /** A bounded compiled-schema LRU (SPEC §13.7's reference 256-entry cache), keyed by CLOSURE
258
+ * digest. The profile walk (incl. member digest verification) runs on EVERY call — only the
259
+ * ajv compilation is skipped on a hit. Sound across callers: two bundles with one closure
260
+ * digest are byte-identical closures, so a hit can never serve another caller's
261
+ * mis-assembled bundle. */
262
+ export function createCompiledContractCache(capacity = SCHEMA_PROFILE.compiledCacheEntries) {
263
+ if (!Number.isSafeInteger(capacity) || capacity < 1)
264
+ throw new Error(`cache capacity ${capacity} is not a positive integer`);
265
+ const lru = new Map();
266
+ return {
267
+ compile(bundle) {
268
+ const closureDigest = assertClosureProfile(bundle);
269
+ const hit = lru.get(closureDigest);
270
+ if (hit) {
271
+ lru.delete(closureDigest); // refresh recency
272
+ lru.set(closureDigest, hit);
273
+ return hit;
274
+ }
275
+ const compiled = makeCompiled(compileWithinBudget(bundle), closureDigest);
276
+ lru.set(closureDigest, compiled);
277
+ if (lru.size > capacity)
278
+ lru.delete(lru.keys().next().value);
279
+ return compiled;
280
+ },
281
+ size: () => lru.size,
282
+ };
283
+ }
284
+ //# sourceMappingURL=schema-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-profile.js","sourceRoot":"","sources":["../src/schema-profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The abstract seam for persisting secret material.
3
+ *
4
+ * Core owns ONLY this tiny value-store contract. The default filesystem adapter (`FsSecretStore`)
5
+ * lives in `@cotal-ai/workspace` because on-disk layout is a workstation concern, not the wire
6
+ * protocol. A closed hosted composition injects its own KMS/Vault-backed implementation at its
7
+ * composition root; nothing here knows it is being hosted.
8
+ *
9
+ * SCOPE — what routes through a `SecretStore`. Only DURABLE HOSTED SECRET BLOBS: the full persisted
10
+ * space trust bundle (operator + account seeds and the account signing seed; only the system-account
11
+ * seed is stripped before disk), the auth service's callout / issuer / owner-secret / service-key
12
+ * material, agent standing creds, and any daemon standing credential the hosted composition persists
13
+ * (renewable ones — delivery / membership-rw — are read via `get` on each refresh, never a one-shot
14
+ * snapshot; rotation-renewed observer / evictor creds are read at start or per use).
15
+ * Machine-local, transient, or non-secret artifacts are NOT `SecretStore` material and remain the
16
+ * local filesystem owner's responsibility: the mesh registry,
17
+ * the transient MCP config, launcher scripts, personas, auth-service discovery (pid/port), the IdP
18
+ * pin, `membership.json`, the login cache, and the actor ledger (authorization DB state, not an
19
+ * exportable blob). Every
20
+ * durable secret that routes through here must be READ through `get` too, or a hosted `put` is a
21
+ * silent no-op while a raw `readFileSync` stays authoritative.
22
+ *
23
+ * KEYS are OPAQUE logical strings built by the owning package. Core assigns them no taxonomy: a
24
+ * KMS key-id / policy / HSM-slot mapping is the closed adapter's concern. Typing the key could not
25
+ * enforce "signing-seed never leaves the HSM" anyway, because {@link SecretStore.get} necessarily
26
+ * exports the value; non-exportable signing, if ever needed, is a separate capability seam
27
+ * (sign / mint), not a richer key here. v1 accepts that signing material DOES enter process memory
28
+ * (e.g. `mintCreds`).
29
+ */
30
+ export interface SecretStore {
31
+ /** The stored value for `key`, or `undefined` if absent. */
32
+ get(key: string): Promise<string | undefined>;
33
+ /** Store `value` under `key`, replacing any prior value AS A WHOLE: a concurrent `get` observes
34
+ * either the complete old value or the complete new one, never a partial or torn intermediate
35
+ * (FS adapter → atomic temp+rename; a managed backend → a conditional / whole-object put). This
36
+ * atomicity is part of the contract because standing daemon/agent creds are re-read live during
37
+ * renewal. Private perms / hardening beyond the atomicity guarantee remain the adapter's concern. */
38
+ put(key: string, value: string): Promise<void>;
39
+ /** Remove `key`. Idempotent. The ONLY portable contract is: after a successful `delete`,
40
+ * `get(key)` returns absent. This is NOT cryptographic shred, revocation, or credential kill —
41
+ * a backend may retain recoverable versions, and any already-issued NATS cred or signing seed
42
+ * stays valid until its credential lifetime ends or broker/key rotation invalidates it (those
43
+ * are mint / renewal / eviction concerns, not `SecretStore`). */
44
+ delete(key: string): Promise<void>;
45
+ }
46
+ //# sourceMappingURL=secret-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-store.d.ts","sourceRoot":"","sources":["../src/secret-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE9C;;;;0GAIsG;IACtG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;;;sEAIkE;IAClE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=secret-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../src/secret-store.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { SpaceAuth } from "./provision.js";
2
+ /**
3
+ * Validate an existing full space trust bundle before a restore or other state mutation.
4
+ *
5
+ * This is read-only: it never generates, rotates, or signs key material, and returns the same
6
+ * validated object. Persisted bundles may omit `sys.signingSeed`; when present, it is validated too.
7
+ */
8
+ export declare function validateSpaceAuth(auth: unknown, expectedSpace?: string): SpaceAuth;
9
+ //# sourceMappingURL=space-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space-auth.d.ts","sourceRoot":"","sources":["../src/space-auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA4DhD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CA2DlF"}
@@ -0,0 +1,126 @@
1
+ import { decode, Types } from "@nats-io/jwt";
2
+ import { fromPublic, fromSeed } from "@nats-io/nkeys";
3
+ import { token } from "./subjects.js";
4
+ function record(value, field) {
5
+ if (!value || typeof value !== "object" || Array.isArray(value))
6
+ throw new Error(`validateSpaceAuth: ${field} must be an object`);
7
+ return value;
8
+ }
9
+ function string(value, field) {
10
+ if (typeof value !== "string" || value.length === 0)
11
+ throw new Error(`validateSpaceAuth: ${field} must be a non-empty string`);
12
+ return value;
13
+ }
14
+ function publicKey(value, field, prefix) {
15
+ let pair;
16
+ try {
17
+ pair = fromPublic(value);
18
+ const pub = pair.getPublicKey();
19
+ if (!pub.startsWith(prefix))
20
+ throw new Error();
21
+ return pub;
22
+ }
23
+ catch {
24
+ throw new Error(`validateSpaceAuth: ${field} is not a valid ${prefix === "A" ? "account" : "operator"} public nkey`);
25
+ }
26
+ finally {
27
+ pair?.clear();
28
+ }
29
+ }
30
+ function seedPublicKey(value, field, prefix) {
31
+ let pair;
32
+ try {
33
+ pair = fromSeed(new TextEncoder().encode(value));
34
+ const pub = pair.getPublicKey();
35
+ if (!pub.startsWith(prefix))
36
+ throw new Error();
37
+ return pub;
38
+ }
39
+ catch {
40
+ throw new Error(`validateSpaceAuth: ${field} is not a valid ${prefix === "A" ? "account" : "operator"} seed`);
41
+ }
42
+ finally {
43
+ pair?.clear();
44
+ }
45
+ }
46
+ function claims(jwt, field) {
47
+ try {
48
+ const decoded = decode(jwt);
49
+ const now = Math.floor(Date.now() / 1000);
50
+ if (decoded.aud !== "NATS")
51
+ throw new Error();
52
+ if (!Number.isSafeInteger(decoded.iat) || decoded.iat < 0)
53
+ throw new Error();
54
+ if (typeof decoded.jti !== "string" || decoded.jti.length === 0)
55
+ throw new Error();
56
+ if (decoded.exp !== undefined && (!Number.isSafeInteger(decoded.exp) || decoded.exp <= now))
57
+ throw new Error();
58
+ if (decoded.nbf !== undefined && (!Number.isSafeInteger(decoded.nbf) || decoded.nbf > now))
59
+ throw new Error();
60
+ return decoded;
61
+ }
62
+ catch {
63
+ throw new Error(`validateSpaceAuth: ${field} is not a currently valid signed NATS JWT`);
64
+ }
65
+ }
66
+ /**
67
+ * Validate an existing full space trust bundle before a restore or other state mutation.
68
+ *
69
+ * This is read-only: it never generates, rotates, or signs key material, and returns the same
70
+ * validated object. Persisted bundles may omit `sys.signingSeed`; when present, it is validated too.
71
+ */
72
+ export function validateSpaceAuth(auth, expectedSpace) {
73
+ const root = record(auth, "auth");
74
+ const operator = record(root.operator, "operator");
75
+ const account = record(root.account, "account");
76
+ const sys = record(root.sys, "sys");
77
+ const space = string(root.space, "space");
78
+ if (!space.trim())
79
+ throw new Error("validateSpaceAuth: space must not be blank");
80
+ if (expectedSpace !== undefined && space !== expectedSpace)
81
+ throw new Error(`validateSpaceAuth: space "${space}" does not match expected space "${expectedSpace}"`);
82
+ const operatorSeed = string(operator.seed, "operator.seed");
83
+ const operatorJwt = string(operator.jwt, "operator.jwt");
84
+ const accountPub = publicKey(string(account.pub, "account.pub"), "account.pub", "A");
85
+ const accountSeed = string(account.seed, "account.seed");
86
+ const accountJwt = string(account.jwt, "account.jwt");
87
+ const signingSeed = string(account.signingSeed, "account.signingSeed");
88
+ const signingPub = publicKey(string(account.signingPub, "account.signingPub"), "account.signingPub", "A");
89
+ const sysPub = publicKey(string(sys.pub, "sys.pub"), "sys.pub", "A");
90
+ const sysJwt = string(sys.jwt, "sys.jwt");
91
+ if (accountPub === sysPub || signingPub === sysPub)
92
+ throw new Error("validateSpaceAuth: data account identities and system account must use distinct nkeys");
93
+ const operatorPub = seedPublicKey(operatorSeed, "operator.seed", "O");
94
+ if (seedPublicKey(accountSeed, "account.seed", "A") !== accountPub)
95
+ throw new Error("validateSpaceAuth: account.seed does not match account.pub");
96
+ if (seedPublicKey(signingSeed, "account.signingSeed", "A") !== signingPub)
97
+ throw new Error("validateSpaceAuth: account.signingSeed does not match account.signingPub");
98
+ if (sys.signingSeed !== undefined) {
99
+ const sysSigningSeed = string(sys.signingSeed, "sys.signingSeed");
100
+ if (seedPublicKey(sysSigningSeed, "sys.signingSeed", "A") !== sysPub)
101
+ throw new Error("validateSpaceAuth: sys.signingSeed does not match sys.pub");
102
+ }
103
+ const operatorClaims = claims(operatorJwt, "operator.jwt");
104
+ const accountClaims = claims(accountJwt, "account.jwt");
105
+ const sysClaims = claims(sysJwt, "sys.jwt");
106
+ publicKey(operatorClaims.sub, "operator JWT subject", "O");
107
+ if (operatorClaims.nats?.type !== Types.Operator || operatorClaims.sub !== operatorPub || operatorClaims.iss !== operatorPub)
108
+ throw new Error("validateSpaceAuth: operator JWT subject, issuer, or type does not match operator.seed");
109
+ if (operatorClaims.name !== `cotal-${token(space)}`)
110
+ throw new Error("validateSpaceAuth: operator JWT name does not match space");
111
+ if (operatorClaims.nats.system_account !== sysPub)
112
+ throw new Error("validateSpaceAuth: operator JWT system account does not match sys.pub");
113
+ if (accountClaims.nats?.type !== Types.Account || accountClaims.sub !== accountPub || accountClaims.iss !== operatorPub)
114
+ throw new Error("validateSpaceAuth: account JWT subject, issuer, or type does not match the operator/account keys");
115
+ if (accountClaims.name !== token(space))
116
+ throw new Error("validateSpaceAuth: account JWT name does not match space");
117
+ const signingKeys = accountClaims.nats.signing_keys;
118
+ if (!Array.isArray(signingKeys) || !signingKeys.includes(signingPub))
119
+ throw new Error("validateSpaceAuth: active account signing key is not trusted as an unscoped signer by account.jwt");
120
+ if (sysClaims.nats?.type !== Types.Account || sysClaims.sub !== sysPub || sysClaims.iss !== operatorPub)
121
+ throw new Error("validateSpaceAuth: system account JWT subject, issuer, or type does not match the operator/system keys");
122
+ if (sysClaims.name !== "SYS")
123
+ throw new Error("validateSpaceAuth: system account JWT name must be SYS");
124
+ return auth;
125
+ }
126
+ //# sourceMappingURL=space-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space-auth.js","sourceRoot":"","sources":["../src/space-auth.ts"],"names":[],"mappings":"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"}