@cotal-ai/auth 0.89.0 → 0.90.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 (106) hide show
  1. package/README.md +11 -0
  2. package/dist/authority-client.d.ts +8 -1
  3. package/dist/authority-client.d.ts.map +1 -1
  4. package/dist/authority-client.js +11 -9
  5. package/dist/authority-client.js.map +1 -1
  6. package/dist/callout.d.ts +3 -0
  7. package/dist/callout.d.ts.map +1 -1
  8. package/dist/callout.js +24 -2
  9. package/dist/callout.js.map +1 -1
  10. package/dist/connect-reader.d.ts +7 -0
  11. package/dist/connect-reader.d.ts.map +1 -1
  12. package/dist/connect-reader.js +16 -1
  13. package/dist/connect-reader.js.map +1 -1
  14. package/dist/credential-ledger.d.ts.map +1 -1
  15. package/dist/credential-ledger.js +7 -1
  16. package/dist/credential-ledger.js.map +1 -1
  17. package/dist/idp.d.ts.map +1 -1
  18. package/dist/idp.js +2 -0
  19. package/dist/idp.js.map +1 -1
  20. package/dist/index.d.ts +5 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +4 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/issuer.d.ts +11 -0
  25. package/dist/issuer.d.ts.map +1 -1
  26. package/dist/issuer.js +29 -1
  27. package/dist/issuer.js.map +1 -1
  28. package/dist/lifecycle-registry.d.ts +6 -0
  29. package/dist/lifecycle-registry.d.ts.map +1 -1
  30. package/dist/lifecycle-registry.js +13 -1
  31. package/dist/lifecycle-registry.js.map +1 -1
  32. package/dist/native-issuance.d.ts +13 -1
  33. package/dist/native-issuance.d.ts.map +1 -1
  34. package/dist/native-issuance.js +76 -10
  35. package/dist/native-issuance.js.map +1 -1
  36. package/dist/native-service-callout.d.ts +38 -0
  37. package/dist/native-service-callout.d.ts.map +1 -0
  38. package/dist/native-service-callout.js +71 -0
  39. package/dist/native-service-callout.js.map +1 -0
  40. package/dist/native-service-gate.d.ts +72 -0
  41. package/dist/native-service-gate.d.ts.map +1 -0
  42. package/dist/native-service-gate.js +219 -0
  43. package/dist/native-service-gate.js.map +1 -0
  44. package/dist/native-service-name.d.ts +17 -0
  45. package/dist/native-service-name.d.ts.map +1 -0
  46. package/dist/native-service-name.js +77 -0
  47. package/dist/native-service-name.js.map +1 -0
  48. package/dist/permissions.js +2 -0
  49. package/dist/permissions.js.map +1 -1
  50. package/dist/plane-claim.d.ts +8 -0
  51. package/dist/plane-claim.d.ts.map +1 -1
  52. package/dist/plane-claim.js +11 -1
  53. package/dist/plane-claim.js.map +1 -1
  54. package/dist/provider.d.ts.map +1 -1
  55. package/dist/provider.js +48 -4
  56. package/dist/provider.js.map +1 -1
  57. package/dist/retirement-barrier.d.ts.map +1 -1
  58. package/dist/retirement-barrier.js +2 -1
  59. package/dist/retirement-barrier.js.map +1 -1
  60. package/dist/root-credential.d.ts.map +1 -1
  61. package/dist/root-credential.js +2 -1
  62. package/dist/root-credential.js.map +1 -1
  63. package/dist/service-authority-client.d.ts +19 -0
  64. package/dist/service-authority-client.d.ts.map +1 -0
  65. package/dist/service-authority-client.js +152 -0
  66. package/dist/service-authority-client.js.map +1 -0
  67. package/dist/service-caller-policy.d.ts +32 -0
  68. package/dist/service-caller-policy.d.ts.map +1 -0
  69. package/dist/service-caller-policy.js +218 -0
  70. package/dist/service-caller-policy.js.map +1 -0
  71. package/dist/service-custody-shapes.d.ts +109 -0
  72. package/dist/service-custody-shapes.d.ts.map +1 -0
  73. package/dist/service-custody-shapes.js +138 -0
  74. package/dist/service-custody-shapes.js.map +1 -0
  75. package/dist/service-custody.d.ts +96 -0
  76. package/dist/service-custody.d.ts.map +1 -0
  77. package/dist/service-custody.js +667 -0
  78. package/dist/service-custody.js.map +1 -0
  79. package/dist/service-host-contract.d.ts +312 -0
  80. package/dist/service-host-contract.d.ts.map +1 -0
  81. package/dist/service-host-contract.js +176 -0
  82. package/dist/service-host-contract.js.map +1 -0
  83. package/dist/service-renewal.d.ts +23 -0
  84. package/dist/service-renewal.d.ts.map +1 -0
  85. package/dist/service-renewal.js +51 -0
  86. package/dist/service-renewal.js.map +1 -0
  87. package/dist/service-root-reader.d.ts +16 -0
  88. package/dist/service-root-reader.d.ts.map +1 -0
  89. package/dist/service-root-reader.js +93 -0
  90. package/dist/service-root-reader.js.map +1 -0
  91. package/dist/session-ledger.d.ts.map +1 -1
  92. package/dist/session-ledger.js +8 -2
  93. package/dist/session-ledger.js.map +1 -1
  94. package/dist/store.d.ts +2 -0
  95. package/dist/store.d.ts.map +1 -1
  96. package/dist/store.js +2 -0
  97. package/dist/store.js.map +1 -1
  98. package/dist/token.d.ts +11 -1
  99. package/dist/token.d.ts.map +1 -1
  100. package/dist/token.js +31 -3
  101. package/dist/token.js.map +1 -1
  102. package/dist/tool-result-prerequisites.d.ts +55 -0
  103. package/dist/tool-result-prerequisites.d.ts.map +1 -0
  104. package/dist/tool-result-prerequisites.js +352 -0
  105. package/dist/tool-result-prerequisites.js.map +1 -0
  106. package/package.json +7 -4
@@ -1,5 +1,5 @@
1
1
  import { fromPublic } from "@nats-io/nkeys";
2
- import { EP_AUTH_MARKER_TTL_MS, epAuthBucket, nativeIssuanceKey } from "@cotal-ai/core";
2
+ import { EP_AUTH_MARKER_TTL_MS, SERVICE_ACCESS_TTL_SECONDS, contractDigest, epAuthBucket, epcredRowKey, nativeIssuanceKey, parseLedgerRow, parseServiceConnectionBinding, parseServiceRegistrationWitness, } from "@cotal-ai/core";
3
3
  import { CLOCK_TOLERANCE_SEC } from "./token.js";
4
4
  import { registryStores } from "./lifecycle-registry.js";
5
5
  const FIELDS = ["v", "space", "owner", "actor", "lifecycleUid", "credentialId", "view", "connId", "iat", "exp"];
@@ -13,6 +13,28 @@ function assertSeconds(v, what) {
13
13
  throw new Error(`natkey: ${what} must be a positive integer of seconds`);
14
14
  return v;
15
15
  }
16
+ function parseServiceEvidence(raw) {
17
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
18
+ throw new Error("natkey: invalid service evidence");
19
+ const o = raw;
20
+ if (Object.keys(o).length !== 3 || Object.keys(o).some((k) => !["witness", "credentialId", "connection"].includes(k))
21
+ || typeof o.credentialId !== "string")
22
+ throw new Error("natkey: invalid service evidence");
23
+ const witness = parseServiceRegistrationWitness(o.witness), connection = parseServiceConnectionBinding(o.connection);
24
+ epcredRowKey(witness.endpoint, witness.instanceId, o.credentialId);
25
+ return { witness, credentialId: o.credentialId, connection };
26
+ }
27
+ async function verifyServiceEvidence(kv, record) {
28
+ const service = record.service;
29
+ const key = epcredRowKey(service.witness.endpoint, service.witness.instanceId, service.credentialId), entry = await kv.get(key);
30
+ if (!entry || entry.operation !== "PUT")
31
+ throw new Error("natkey: service issuance evidence is unavailable");
32
+ const row = parseLedgerRow(entry.value, key);
33
+ if (row.state !== "active" || row.holderPrincipal !== `${record.owner}.${record.actor}` || row.exp !== record.exp
34
+ || row.sourceChain.length !== 1 || row.sourceChain[0] !== "root" || !row.serviceConnection
35
+ || contractDigest(row.serviceConnection) !== contractDigest(service.connection))
36
+ throw new Error("natkey: service issuance evidence does not match the connection");
37
+ }
16
38
  /** Build the record from the validated token alone: never from a fresh alias lookup. */
17
39
  export function nativeIssuanceRecord(space, i) {
18
40
  const t = i.token;
@@ -24,14 +46,26 @@ export function nativeIssuanceRecord(space, i) {
24
46
  const iat = assertSeconds(i.iat, "iat"), exp = assertSeconds(i.exp, "exp");
25
47
  if (exp <= iat)
26
48
  throw new Error("natkey: exp must follow iat");
27
- return { v: 1, space, owner: t.owner, actor: t.act.actor, lifecycleUid, credentialId, view: t.act.view ?? "agent", connId: i.connId, iat, exp };
49
+ const record = { v: 1, space, owner: t.owner, actor: t.act.actor, lifecycleUid, credentialId,
50
+ view: t.act.view ?? "agent", connId: i.connId, iat, exp };
51
+ if (t.act.view === "service-endpoint") {
52
+ if (!i.service || !t.act.service || exp > t.exp)
53
+ throw new Error("natkey: service issuance requires bounded native evidence");
54
+ record.service = parseServiceEvidence({ ...i.service, witness: t.act.service.witness });
55
+ if (record.service.connection.userNkey !== i.userNkey)
56
+ throw new Error("natkey: service evidence names a different user key");
57
+ }
58
+ else if (i.service !== undefined)
59
+ throw new Error("natkey: ordinary issuance cannot carry service evidence");
60
+ return record.service ? parseNativeIssuanceRecord(record) : record;
28
61
  }
29
62
  /** Parse a stored row; anything but the closed v1 shape refuses. */
30
63
  export function parseNativeIssuanceRecord(raw) {
31
64
  if (typeof raw !== "object" || raw === null || Array.isArray(raw))
32
65
  throw new Error("natkey: record is not an object");
33
66
  const keys = Object.keys(raw);
34
- if (keys.length !== FIELDS.length || !FIELDS.every((f) => keys.includes(f)))
67
+ if (keys.length !== FIELDS.length + (Object.hasOwn(raw, "service") ? 1 : 0) || !FIELDS.every((f) => keys.includes(f))
68
+ || keys.some((key) => key !== "service" && !FIELDS.includes(key)))
35
69
  throw new Error(`natkey: record fields ${JSON.stringify(keys.sort())} are not the closed v1 set`);
36
70
  const r = raw;
37
71
  if (r.v !== 1)
@@ -41,6 +75,16 @@ export function parseNativeIssuanceRecord(raw) {
41
75
  throw new Error(`natkey: record ${f} is not a non-empty string`);
42
76
  assertSeconds(r.iat, "iat");
43
77
  assertSeconds(r.exp, "exp");
78
+ if ((r.view === "service-endpoint") !== Object.hasOwn(r, "service"))
79
+ throw new Error("natkey: service view and evidence must occur together");
80
+ if (r.service !== undefined) {
81
+ const service = parseServiceEvidence(r.service), witness = service.witness;
82
+ if (r.space !== witness.space || r.owner !== witness.principal.owner || r.actor !== witness.principal.actor
83
+ || r.lifecycleUid !== witness.principal.lifecycleUid || r.credentialId !== witness.rootCredentialId
84
+ || r.exp <= r.iat || r.exp > r.iat + SERVICE_ACCESS_TTL_SECONDS)
85
+ throw new Error("natkey: service evidence does not match its native root and lifetime");
86
+ return { ...r, service };
87
+ }
44
88
  return r;
45
89
  }
46
90
  /**
@@ -54,8 +98,21 @@ export function makeNativeIssuanceRecorder(registry, fence) {
54
98
  return async (i) => {
55
99
  const key = assertUserNkey(i.userNkey);
56
100
  const record = nativeIssuanceRecord(space, i);
57
- await authKv.create(key, new TextEncoder().encode(JSON.stringify(record)));
58
- await fence(i.token);
101
+ const token = record.service ? structuredClone(i.token) : i.token;
102
+ const bytes = new TextEncoder().encode(JSON.stringify(record));
103
+ if (record.service) {
104
+ await verifyServiceEvidence(authKv, record);
105
+ await authKv.put(key, bytes, { previousSeq: 0 });
106
+ await verifyServiceEvidence(authKv, record);
107
+ const stored = await readNativeIssuance(authKv, i.userNkey);
108
+ if (!stored || contractDigest(stored) !== contractDigest(record))
109
+ throw new Error("natkey: service receipt changed before release");
110
+ }
111
+ else
112
+ await authKv.create(key, bytes);
113
+ await fence(token);
114
+ if (record.service && record.exp <= Math.floor(Date.now() / 1000))
115
+ throw new Error("natkey: service issuance expired before release");
59
116
  };
60
117
  }
61
118
  /** Leader-read one key's evidence (the auth bucket is not Direct-capable). Absent is `undefined`. */
@@ -63,7 +120,10 @@ export async function readNativeIssuance(kv, userNkey) {
63
120
  const entry = await kv.get(assertUserNkey(userNkey));
64
121
  if (!entry || entry.operation !== "PUT")
65
122
  return undefined;
66
- return parseNativeIssuanceRecord(entry.json());
123
+ const record = parseNativeIssuanceRecord(entry.json());
124
+ if (record.service && record.service.connection.userNkey !== userNkey)
125
+ throw new Error("natkey: service receipt key does not match its connection");
126
+ return record;
67
127
  }
68
128
  /**
69
129
  * Remove the rows whose minted JWT expired more than the clock tolerance ago (a session-caller's
@@ -71,13 +131,14 @@ export async function readNativeIssuance(kv, userNkey) {
71
131
  * `STREAM.MSG.GET` `next_by_subj` read over `natkey.` (no consumer: none may be created on the auth
72
132
  * bucket), and each removal is a KV purge pinned to the exact sequence read. A row that does not
73
133
  * parse throws: corrupt evidence is the caller's fault to surface, never a skipped row. The purge
74
- * marker carries the bucket's own marker TTL, so it expires too.
134
+ * marker carries the bucket's own marker TTL, so it expires too. Expired service evidence is
135
+ * retained: elapsed JWT time alone is not topology-qualified absence or terminal retirement.
75
136
  */
76
137
  export async function pruneNativeIssuance(registry, nowSec) {
77
138
  const { authKv, jsm, space } = registryStores(registry);
78
139
  const bucket = epAuthBucket(space);
79
140
  const prefix = `$KV.${bucket}.`;
80
- let seq = 1, live = 0, pruned = 0;
141
+ let seq = 1, live = 0, pruned = 0, retainedService = 0;
81
142
  for (;;) {
82
143
  const m = await jsm.streams.getMessage(`KV_${bucket}`, { seq, next_by_subj: `${prefix}natkey.>` });
83
144
  if (!m)
@@ -90,13 +151,18 @@ export async function pruneNativeIssuance(registry, nowSec) {
90
151
  if (assertUserNkey(key.slice("natkey.".length)) !== key)
91
152
  throw new Error(`natkey: stored subject ${JSON.stringify(m.subject)} is not a natkey row`);
92
153
  const record = parseNativeIssuanceRecord(m.json());
93
- if (record.exp + CLOCK_TOLERANCE_SEC < nowSec) {
154
+ if (record.service && nativeIssuanceKey(record.service.connection.userNkey) !== key)
155
+ throw new Error("natkey: service receipt key does not match its connection");
156
+ if (record.exp + CLOCK_TOLERANCE_SEC < nowSec && record.service) {
157
+ retainedService++;
158
+ }
159
+ else if (record.exp + CLOCK_TOLERANCE_SEC < nowSec) {
94
160
  await authKv.purge(key, { previousSeq: m.seq, ttl: `${EP_AUTH_MARKER_TTL_MS / 1000}s` });
95
161
  pruned++;
96
162
  }
97
163
  else
98
164
  live++;
99
165
  }
100
- return { live, pruned };
166
+ return { live, pruned, retainedService };
101
167
  }
102
168
  //# sourceMappingURL=native-issuance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"native-issuance.js","sourceRoot":"","sources":["../src/native-issuance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"native-issuance.js","sourceRoot":"","sources":["../src/native-issuance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { type ServiceConnectionBinding, type ServiceRegistrationWitness } from "@cotal-ai/core";
2
+ import type { ConnectReader } from "./connect-reader.js";
3
+ import { type LifecycleRegistry } from "./lifecycle-registry.js";
4
+ import { type ServiceAssignmentBinding } from "./native-service-gate.js";
5
+ import type { ValidatedUserToken } from "./token.js";
6
+ export interface NativeServiceCalloutAuthority {
7
+ readonly space: string;
8
+ readonly accountPublicKey: string;
9
+ }
10
+ interface ServiceCalloutContext {
11
+ connection: ServiceConnectionBinding;
12
+ inboxNonce: string;
13
+ admittedAt: number;
14
+ }
15
+ interface ServiceCalloutResult {
16
+ jwt: string;
17
+ principal: string;
18
+ exp: number;
19
+ }
20
+ /** Native host composition only. Assignment lookup and restore/mutation readiness belong to the
21
+ * host; neither callback is a public approval hook. Services receive no registry or signing key.
22
+ */
23
+ export declare function createNativeServiceCalloutAuthority(opts: {
24
+ registry: LifecycleRegistry;
25
+ reader: () => ConnectReader;
26
+ dataAccount: {
27
+ pub: string;
28
+ signingSeed: string;
29
+ };
30
+ resolveAssignment: (witness: ServiceRegistrationWitness) => Promise<ServiceAssignmentBinding>;
31
+ readClusterArtifact: (digest: string) => unknown | Promise<unknown>;
32
+ assertOpen: () => void;
33
+ }): NativeServiceCalloutAuthority;
34
+ /** A structural object cannot opt into native service minting or select another tenant account. */
35
+ export declare function assertNativeServiceCalloutAuthority(authority: NativeServiceCalloutAuthority, space: string, accountPublicKey: string): void;
36
+ export declare function issueNativeServiceCallout(authority: NativeServiceCalloutAuthority, token: ValidatedUserToken, context: ServiceCalloutContext): Promise<ServiceCalloutResult>;
37
+ export {};
38
+ //# sourceMappingURL=native-service-callout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-service-callout.d.ts","sourceRoot":"","sources":["../src/native-service-callout.ts"],"names":[],"mappings":"AAAA,OAAO,EAE+D,KAAK,wBAAwB,EAAE,KAAK,0BAA0B,EACnI,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjF,OAAO,EAAkD,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,6BAA6B;IAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE;AAC5G,UAAU,qBAAqB;IAAG,UAAU,EAAE,wBAAwB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AAChH,UAAU,oBAAoB;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAI9E;;GAEG;AACH,wBAAgB,mCAAmC,CAAC,IAAI,EAAE;IACxD,QAAQ,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,MAAM,aAAa,CAAC;IAAC,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5G,iBAAiB,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC9F,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,IAAI,CAAC;CAC7F,GAAG,6BAA6B,CA6ChC;AAED,mGAAmG;AACnG,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,6BAA6B,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAG3I;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,6BAA6B,EAAE,KAAK,EAAE,kBAAkB,EAC3G,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAI/D"}
@@ -0,0 +1,71 @@
1
+ import { SERVICE_ACCESS_TTL_SECONDS, authorizeServeGrant, contractDigest, mintServiceCalloutJwt, parseServiceConnectionBinding, parseServiceRegistrationWitness, principalKey, serveIssuanceGateKv, } from "@cotal-ai/core";
2
+ import { registryStores } from "./lifecycle-registry.js";
3
+ import { makeNativeIssuanceRecorder } from "./native-issuance.js";
4
+ import { readNativeServiceAccess, readNativeServiceGate } from "./native-service-gate.js";
5
+ import { nativeServiceNameAuthority } from "./native-service-name.js";
6
+ const authorities = new WeakMap();
7
+ /** Native host composition only. Assignment lookup and restore/mutation readiness belong to the
8
+ * host; neither callback is a public approval hook. Services receive no registry or signing key.
9
+ */
10
+ export function createNativeServiceCalloutAuthority(opts) {
11
+ const { registry, reader, resolveAssignment, readClusterArtifact, assertOpen } = opts;
12
+ const dataAccount = { ...opts.dataAccount }, stores = registryStores(registry), space = stores.space;
13
+ const authority = Object.freeze({ space, accountPublicKey: dataAccount.pub });
14
+ const names = nativeServiceNameAuthority(registry, { space, accountPublicKey: dataAccount.pub });
15
+ authorities.set(authority, async (raw, supplied) => {
16
+ const token = structuredClone(raw), connection = parseServiceConnectionBinding(supplied.connection);
17
+ const { inboxNonce, admittedAt } = supplied, expiresAt = Math.min(token.exp, admittedAt + SERVICE_ACCESS_TTL_SECONDS);
18
+ if (!Number.isSafeInteger(admittedAt) || admittedAt <= 0 || admittedAt > Math.floor(Date.now() / 1000)
19
+ || !Number.isSafeInteger(expiresAt) || expiresAt <= Math.floor(Date.now() / 1000))
20
+ throw new Error("service callout requires its original live admission deadline");
21
+ if (token.act.view !== "service-endpoint" || !token.act.service)
22
+ throw new Error("service callout requires a validated service bearer");
23
+ const witness = parseServiceRegistrationWitness(token.act.service.witness);
24
+ if (witness.accountPublicKey !== dataAccount.pub || witness.space !== space)
25
+ throw new Error("service callout bearer belongs to another native account or space");
26
+ assertOpen();
27
+ const binding = { ...await resolveAssignment(witness) }, bindingDigest = contractDigest(binding);
28
+ if (binding.accountPublicKey !== dataAccount.pub || binding.space !== space)
29
+ throw new Error("service callout assignment belongs to another native account or space");
30
+ await readNativeServiceAccess(registry, reader(), binding, token, expiresAt);
31
+ const serve = await authorizeServeGrant(stores.recordsKv, { space, endpoint: witness.endpoint, instanceId: witness.instanceId,
32
+ epoch: witness.processEpoch, holder: { owner: witness.principal.owner }, authority: names, readClusterArtifact,
33
+ readProcessEpoch: async () => {
34
+ const gate = await readNativeServiceGate(registry, binding);
35
+ if (!gate)
36
+ throw new Error("service callout has no native gate");
37
+ return gate.row.processEpoch;
38
+ } });
39
+ assertOpen();
40
+ const minted = await mintServiceCalloutJwt({ space, account: dataAccount }, { serve,
41
+ gate: serveIssuanceGateKv(stores.authKv, space, { endpoint: witness.endpoint, instanceId: witness.instanceId }),
42
+ principal: witness.principal, connection, inboxNonce, admittedAt, accessExpiresAt: token.exp, expiresAt });
43
+ const record = makeNativeIssuanceRecorder(registry, async (currentToken) => {
44
+ assertOpen();
45
+ const current = { ...await resolveAssignment(witness) };
46
+ if (contractDigest(current) !== bindingDigest)
47
+ throw new Error("service assignment changed before callout release");
48
+ await readNativeServiceAccess(registry, reader(), current, currentToken, expiresAt);
49
+ assertOpen();
50
+ });
51
+ await record({ userNkey: connection.userNkey, token, connId: inboxNonce, iat: minted.iat, exp: minted.exp,
52
+ service: { credentialId: minted.credentialId, connection } });
53
+ assertOpen();
54
+ if (expiresAt <= Math.floor(Date.now() / 1000))
55
+ throw new Error("service callout expired before response");
56
+ return { jwt: minted.jwt, principal: principalKey(witness.principal.owner, witness.principal.actor).key, exp: expiresAt };
57
+ });
58
+ return authority;
59
+ }
60
+ /** A structural object cannot opt into native service minting or select another tenant account. */
61
+ export function assertNativeServiceCalloutAuthority(authority, space, accountPublicKey) {
62
+ if (!authorities.has(authority) || authority.space !== space || authority.accountPublicKey !== accountPublicKey)
63
+ throw new Error("service callout authority is not native or belongs to another account/space");
64
+ }
65
+ export function issueNativeServiceCallout(authority, token, context) {
66
+ const issue = authorities.get(authority);
67
+ if (!issue)
68
+ throw new Error("service callout authority is not native");
69
+ return issue(token, context);
70
+ }
71
+ //# sourceMappingURL=native-service-callout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-service-callout.js","sourceRoot":"","sources":["../src/native-service-callout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { type EndpointGateRow, type EpCapability, type ServiceGateAuthority, type ServiceRegistrationWitness } from "@cotal-ai/core";
2
+ import type { ConnectReader } from "./connect-reader.js";
3
+ import type { ValidatedUserToken } from "./token.js";
4
+ import { type LifecycleRegistry } from "./lifecycle-registry.js";
5
+ export interface ServiceAssignmentBinding {
6
+ accountPublicKey: string;
7
+ space: string;
8
+ owner: string;
9
+ endpoint: string;
10
+ instanceId: string;
11
+ lifecycleUid: string;
12
+ assignmentDigest: string;
13
+ }
14
+ type ServiceRow = EndpointGateRow & {
15
+ authorityFamily: "service";
16
+ serviceAuthority: ServiceGateAuthority;
17
+ };
18
+ interface ServiceGateRead {
19
+ row: ServiceRow;
20
+ revision: number;
21
+ }
22
+ /** Internal host storage seam. Consent and name authority are not established by a gate write. */
23
+ export declare function readNativeServiceGate(reg: LifecycleRegistry, binding: ServiceAssignmentBinding): Promise<ServiceGateRead | undefined>;
24
+ /** Package-internal pure endpoint-gate rows for a writer that issues, bounds and re-checks every
25
+ * request itself. No I/O: the same rows and checks the helpers below write and read. */
26
+ export interface ServiceGateRows {
27
+ readonly key: string;
28
+ /** Parse bytes read at `key`; `conflict` when they belong to another immutable assignment. */
29
+ parse(value: Uint8Array): ServiceRow;
30
+ /** Bytes of the pending-root row that a zero-history create writes. */
31
+ readonly pending: Uint8Array;
32
+ /** Bytes of the frozen revoked row that a zero-history create writes before the gate exists. */
33
+ uncreatedFence(operationId: string): Uint8Array;
34
+ /** Bytes of the deny-new successor of `row`, or `undefined` when it is already revoked. */
35
+ deny(row: ServiceRow, operationId: string): Uint8Array | undefined;
36
+ }
37
+ /** The pure endpoint-gate rows of one assignment in this registry's space. */
38
+ export declare function serviceGateRows(reg: LifecycleRegistry, binding: ServiceAssignmentBinding): ServiceGateRows;
39
+ /** Create the unmintable endpoint gate before native root activation. Never adopts a different assignment. */
40
+ export declare function createPendingServiceGate(reg: LifecycleRegistry, binding: ServiceAssignmentBinding): Promise<ServiceGateRead>;
41
+ /** Current native access prerequisites, not a serving grant or an issuance release fence.
42
+ * The host supplies an already signature-validated token and fixes expiresAt before its first
43
+ * authority read. Final issuance still needs a fresh check and the native serving gate CAS.
44
+ */
45
+ export declare function readNativeServiceAccess(reg: LifecycleRegistry, reader: ConnectReader, expected: ServiceAssignmentBinding, raw: ValidatedUserToken, expiresAt: number): Promise<{
46
+ witness: ServiceRegistrationWitness;
47
+ gateRevision: number;
48
+ expiresAt: number;
49
+ }>;
50
+ /** Final approval CAS. The host must first verify the proposal, owner consent and operator target policy. */
51
+ export declare function approveNativeServiceGate(reg: LifecycleRegistry, binding: ServiceAssignmentBinding, args: {
52
+ expectedRevision: number;
53
+ rootCredentialId: string;
54
+ approvalDigest: string;
55
+ nameAuthorityRevision: number;
56
+ approvalExpiresAt: number | null;
57
+ callerCeiling: EpCapability[];
58
+ }): Promise<ServiceGateRead>;
59
+ /** The host withholds both access and renewal material until this monotonic activation CAS wins. */
60
+ export declare function markNativeServiceActivated(reg: LifecycleRegistry, binding: ServiceAssignmentBinding, args: {
61
+ expectedRevision: number;
62
+ witness: ServiceRegistrationWitness;
63
+ }): Promise<ServiceGateRead>;
64
+ /** Durable deny-new only. This is never a terminal retirement result or broker absence proof. */
65
+ export declare function denyNativeServiceGate(reg: LifecycleRegistry, binding: ServiceAssignmentBinding, args: {
66
+ expectedRevision: number;
67
+ operationId: string;
68
+ }): Promise<ServiceGateRead>;
69
+ /** Fence cancellation before the endpoint gate exists. Native UID cancellation remains a separate required barrier. */
70
+ export declare function fenceUncreatedServiceGate(reg: LifecycleRegistry, binding: ServiceAssignmentBinding, operationId: string): Promise<ServiceGateRead>;
71
+ export {};
72
+ //# sourceMappingURL=native-service-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-service-gate.d.ts","sourceRoot":"","sources":["../src/native-service-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,219 @@
1
+ import { EpEnvelopeError, SERVICE_ACCESS_TTL_SECONDS, assertLifecycleToken, createRowByteIdempotent, epgateKey, isCasLoss, parseEndpointCapabilities, parseEndpointGate, parseServiceRegistrationWitness, principalKey, serviceEndpointActor, serviceGateApprovalLive, } from "@cotal-ai/core";
2
+ import { readNativeServiceName } from "./native-service-name.js";
3
+ import { registryStores } from "./lifecycle-registry.js";
4
+ import { readConnectServiceRoot, readRegistryServiceRoot } from "./service-root-reader.js";
5
+ const enc = new TextEncoder();
6
+ const bytes = (row) => enc.encode(JSON.stringify(row));
7
+ const conflict = (message) => { throw new EpEnvelopeError("conflict", message); };
8
+ function coordinates(reg, binding) {
9
+ const stores = registryStores(reg);
10
+ if (stores.space !== binding.space)
11
+ throw new EpEnvelopeError("permission-denied", "service assignment belongs to another space");
12
+ const actor = serviceEndpointActor(binding);
13
+ return { kv: stores.authKv, key: epgateKey(binding.endpoint, binding.instanceId), actor, principal: principalKey(binding.owner, actor).key };
14
+ }
15
+ function parseFor(binding, key, principal, value) {
16
+ const row = parseEndpointGate(value, key);
17
+ if (row.authorityFamily !== "service" || !row.serviceAuthority || row.principal !== principal
18
+ || row.serviceAuthority.assignmentDigest !== binding.assignmentDigest || row.serviceAuthority.lifecycleUid !== binding.lifecycleUid)
19
+ conflict("service gate belongs to another immutable assignment");
20
+ return row;
21
+ }
22
+ /** Internal host storage seam. Consent and name authority are not established by a gate write. */
23
+ export async function readNativeServiceGate(reg, binding) {
24
+ const { kv, key, principal } = coordinates(reg, binding);
25
+ const entry = await kv.get(key);
26
+ if (!entry)
27
+ return undefined;
28
+ if (entry.operation !== "PUT")
29
+ throw new EpEnvelopeError("failed-precondition", "service gate is deleted; absence cannot be inferred from a tombstone");
30
+ return { row: parseFor(binding, key, principal, entry.value), revision: entry.revision };
31
+ }
32
+ function pendingRow(reg, binding) {
33
+ const { key, principal } = coordinates(reg, binding);
34
+ const row = {
35
+ state: "open", generation: 0, processEpoch: 0, registrationRevision: 0, nameAuthorityRevision: 0,
36
+ principal, authorityFamily: "service", serviceAuthority: {
37
+ v: 1, assignmentDigest: binding.assignmentDigest, lifecycleUid: binding.lifecycleUid,
38
+ state: "pending-root", rootCredentialId: null, rootExpiresAt: null, approvalDigest: null,
39
+ approvalExpiresAt: null, callerCeiling: [], activationIssued: false,
40
+ },
41
+ };
42
+ parseEndpointGate(bytes(row), key);
43
+ return row;
44
+ }
45
+ function deniedRow(row, operationId) {
46
+ assertLifecycleToken(operationId, "operationId");
47
+ if (row.serviceAuthority.state === "revoked")
48
+ return undefined;
49
+ const authority = { ...row.serviceAuthority, state: "revoked" };
50
+ return row.state === "open"
51
+ ? { ...row, state: "frozen", op: { opId: operationId, kind: "retirement" }, serviceAuthority: authority }
52
+ : { ...row, serviceAuthority: authority };
53
+ }
54
+ function uncreatedFenceRow(reg, binding, operationId) {
55
+ assertLifecycleToken(operationId, "operationId");
56
+ const { key } = coordinates(reg, binding), pending = pendingRow(reg, binding);
57
+ const row = { ...pending, state: "frozen", op: { opId: operationId, kind: "retirement" },
58
+ serviceAuthority: { ...pending.serviceAuthority, state: "revoked" } };
59
+ parseEndpointGate(bytes(row), key);
60
+ return row;
61
+ }
62
+ /** The pure endpoint-gate rows of one assignment in this registry's space. */
63
+ export function serviceGateRows(reg, binding) {
64
+ const { key, principal } = coordinates(reg, binding), frozenBinding = { ...binding };
65
+ return Object.freeze({
66
+ key, pending: bytes(pendingRow(reg, frozenBinding)),
67
+ parse: (value) => parseFor(frozenBinding, key, principal, value),
68
+ uncreatedFence: (operationId) => bytes(uncreatedFenceRow(reg, frozenBinding, operationId)),
69
+ deny: (row, operationId) => {
70
+ const next = deniedRow(row, operationId);
71
+ if (next === undefined)
72
+ return undefined;
73
+ const encoded = bytes(next);
74
+ parseEndpointGate(encoded, key);
75
+ return encoded;
76
+ },
77
+ });
78
+ }
79
+ /** Create the unmintable endpoint gate before native root activation. Never adopts a different assignment. */
80
+ export async function createPendingServiceGate(reg, binding) {
81
+ const { kv, key } = coordinates(reg, binding);
82
+ await createRowByteIdempotent(kv, key, pendingRow(reg, binding));
83
+ const created = await readNativeServiceGate(reg, binding);
84
+ if (!created)
85
+ throw new EpEnvelopeError("unavailable", "created service gate is not readable; retain the operation identity");
86
+ return created;
87
+ }
88
+ async function current(reg, binding, expectedRevision) {
89
+ const found = await readNativeServiceGate(reg, binding);
90
+ if (!found || found.revision !== expectedRevision)
91
+ conflict("service gate revision changed");
92
+ return found;
93
+ }
94
+ async function replace(reg, binding, before, row) {
95
+ const { kv, key } = coordinates(reg, binding);
96
+ const encoded = bytes(row);
97
+ parseEndpointGate(encoded, key);
98
+ try {
99
+ return { row, revision: await kv.update(key, encoded, before.revision) };
100
+ }
101
+ catch (error) {
102
+ if (isCasLoss(error))
103
+ conflict("service gate changed before its transition committed");
104
+ throw new EpEnvelopeError("unavailable", "service gate transition outcome is unknown; retain the operation identity");
105
+ }
106
+ }
107
+ async function rootExpiry(reg, binding, rootCredentialId, nowMs) {
108
+ return (await readRegistryServiceRoot(reg, binding, rootCredentialId, nowMs)).expiresAt;
109
+ }
110
+ /** Current native access prerequisites, not a serving grant or an issuance release fence.
111
+ * The host supplies an already signature-validated token and fixes expiresAt before its first
112
+ * authority read. Final issuance still needs a fresh check and the native serving gate CAS.
113
+ */
114
+ export async function readNativeServiceAccess(reg, reader, expected, raw, expiresAt) {
115
+ const binding = { ...expected }, now = Math.floor(Date.now() / 1000);
116
+ if (raw.act.view !== "service-endpoint" || raw.act.service?.duty !== "serve")
117
+ throw new EpEnvelopeError("permission-denied", "native service access requires a validated service bearer");
118
+ const witness = parseServiceRegistrationWitness(raw.act.service.witness);
119
+ const token = { ...raw, scope: [...raw.scope], act: { ...raw.act,
120
+ scope: raw.act.scope === undefined ? undefined : [...raw.act.scope], service: { duty: "serve", witness } } };
121
+ const { actor } = coordinates(reg, binding);
122
+ if (reader.space !== binding.space || token.space !== binding.space || token.owner !== binding.owner
123
+ || token.act.owner !== binding.owner || token.act.actor !== actor || token.act.lifecycleUid !== binding.lifecycleUid
124
+ || token.act.credentialId !== witness.rootCredentialId || token.credentialId !== witness.rootCredentialId
125
+ || token.scope.length || token.act.scope?.length || witness.accountPublicKey !== binding.accountPublicKey
126
+ || witness.space !== binding.space || witness.endpoint !== binding.endpoint || witness.instanceId !== binding.instanceId
127
+ || witness.principal.owner !== binding.owner || witness.principal.actor !== actor || witness.principal.lifecycleUid !== binding.lifecycleUid)
128
+ throw new EpEnvelopeError("permission-denied", "service bearer does not bind the native assignment");
129
+ if (!Number.isSafeInteger(expiresAt) || !Number.isSafeInteger(token.exp) || expiresAt <= now
130
+ || expiresAt > token.exp || expiresAt > now + SERVICE_ACCESS_TTL_SECONDS)
131
+ throw new EpEnvelopeError("expired", "service access requires its original bounded expiry");
132
+ // The native cred root and the endpoint's epcred issuance family are distinct authorities.
133
+ const connectRoot = await readConnectServiceRoot(reader, binding, witness.rootCredentialId, Date.now());
134
+ const rootExpiresAt = await rootExpiry(reg, binding, witness.rootCredentialId, Date.now());
135
+ const found = await readNativeServiceGate(reg, binding);
136
+ if (!found)
137
+ throw new EpEnvelopeError("permission-denied", "service assignment has no native gate");
138
+ const { row } = found, authority = row.serviceAuthority, stamp = authority.registration;
139
+ if (row.state !== "open" || !authority.activationIssued || authority.pendingRegistration !== undefined
140
+ || !serviceGateApprovalLive(authority, Math.floor(Date.now() / 1000)) || !stamp
141
+ || authority.rootCredentialId !== witness.rootCredentialId || authority.approvalDigest !== witness.approvalDigest
142
+ || row.processEpoch !== witness.processEpoch || row.registrationRevision !== witness.registrationRevision
143
+ || row.nameAuthorityRevision !== witness.nameAuthorityRevision || stamp.processEpoch !== witness.processEpoch
144
+ || stamp.registrationRevision !== witness.registrationRevision || stamp.nameAuthorityRevision !== witness.nameAuthorityRevision
145
+ || stamp.requestId !== witness.registrationRequestId || stamp.registrationProof !== witness.registrationProof)
146
+ throw new EpEnvelopeError("permission-denied", "service access does not match the current activated registration");
147
+ if (expiresAt > connectRoot.expiresAt || expiresAt > rootExpiresAt || expiresAt > authority.rootExpiresAt
148
+ || (authority.approvalExpiresAt !== null && expiresAt > authority.approvalExpiresAt))
149
+ throw new EpEnvelopeError("expired", "service access outlives its native root or approval");
150
+ const name = await readNativeServiceName(reg, binding, binding.endpoint);
151
+ if (!name || name.owner !== binding.owner || name.revision !== witness.nameAuthorityRevision)
152
+ throw new EpEnvelopeError("permission-denied", "service access does not match the native name binding");
153
+ const finalGate = await readNativeServiceGate(reg, binding);
154
+ if (!finalGate || finalGate.revision !== found.revision)
155
+ throw new EpEnvelopeError("conflict", "service authority changed during the access read");
156
+ const finalRoot = await readConnectServiceRoot(reader, binding, witness.rootCredentialId, Date.now());
157
+ if (finalRoot.uidRevision !== connectRoot.uidRevision || finalRoot.headRevision !== connectRoot.headRevision
158
+ || finalRoot.gateRevision !== connectRoot.gateRevision || finalRoot.rootRevision !== connectRoot.rootRevision)
159
+ throw new EpEnvelopeError("conflict", "service native root authority changed during the access read");
160
+ if (expiresAt <= Math.floor(Date.now() / 1000))
161
+ throw new EpEnvelopeError("expired", "service access expired during native authorization");
162
+ return { witness, gateRevision: found.revision, expiresAt };
163
+ }
164
+ /** Final approval CAS. The host must first verify the proposal, owner consent and operator target policy. */
165
+ export async function approveNativeServiceGate(reg, binding, args) {
166
+ const found = await current(reg, binding, args.expectedRevision);
167
+ if (found.row.state !== "open" || found.row.serviceAuthority.state !== "pending-root")
168
+ conflict("only the pending root assignment can receive its first approval");
169
+ if (!Number.isSafeInteger(args.nameAuthorityRevision) || args.nameAuthorityRevision <= 0)
170
+ throw new EpEnvelopeError("failed-precondition", "service approval requires its native name binding revision");
171
+ const now = Date.now();
172
+ const authority = {
173
+ ...found.row.serviceAuthority, state: "approved", rootCredentialId: args.rootCredentialId,
174
+ rootExpiresAt: await rootExpiry(reg, binding, args.rootCredentialId, now), approvalDigest: args.approvalDigest,
175
+ approvalExpiresAt: args.approvalExpiresAt, callerCeiling: parseEndpointCapabilities(args.callerCeiling),
176
+ };
177
+ if (!serviceGateApprovalLive(authority, Math.floor(now / 1000)))
178
+ throw new EpEnvelopeError("expired", "service approval has already expired");
179
+ return replace(reg, binding, found, { ...found.row, nameAuthorityRevision: args.nameAuthorityRevision, serviceAuthority: authority });
180
+ }
181
+ /** The host withholds both access and renewal material until this monotonic activation CAS wins. */
182
+ export async function markNativeServiceActivated(reg, binding, args) {
183
+ const witness = parseServiceRegistrationWitness(args.witness);
184
+ const found = await current(reg, binding, args.expectedRevision), row = found.row, authority = row.serviceAuthority;
185
+ const { actor } = coordinates(reg, binding);
186
+ if (witness.accountPublicKey !== binding.accountPublicKey || witness.space !== binding.space
187
+ || witness.endpoint !== binding.endpoint || witness.instanceId !== binding.instanceId
188
+ || witness.principal.owner !== binding.owner || witness.principal.actor !== actor
189
+ || witness.principal.lifecycleUid !== binding.lifecycleUid || witness.rootCredentialId !== authority.rootCredentialId
190
+ || witness.approvalDigest !== authority.approvalDigest || witness.processEpoch !== row.processEpoch
191
+ || witness.registrationRevision !== row.registrationRevision || witness.nameAuthorityRevision !== row.nameAuthorityRevision
192
+ || !authority.registration || witness.registrationRequestId !== authority.registration.requestId || witness.registrationProof !== authority.registration.registrationProof)
193
+ conflict("activation witness does not match the current service registration");
194
+ const now = Date.now();
195
+ if (row.state !== "open" || !serviceGateApprovalLive(authority, Math.floor(now / 1000)))
196
+ throw new EpEnvelopeError("expired", "service approval no longer permits activation");
197
+ await rootExpiry(reg, binding, witness.rootCredentialId, now);
198
+ if (authority.activationIssued)
199
+ return found;
200
+ return replace(reg, binding, found, { ...row, serviceAuthority: { ...authority, activationIssued: true } });
201
+ }
202
+ /** Durable deny-new only. This is never a terminal retirement result or broker absence proof. */
203
+ export async function denyNativeServiceGate(reg, binding, args) {
204
+ assertLifecycleToken(args.operationId, "operationId");
205
+ const found = await current(reg, binding, args.expectedRevision);
206
+ const next = deniedRow(found.row, args.operationId);
207
+ return next === undefined ? found : replace(reg, binding, found, next);
208
+ }
209
+ /** Fence cancellation before the endpoint gate exists. Native UID cancellation remains a separate required barrier. */
210
+ export async function fenceUncreatedServiceGate(reg, binding, operationId) {
211
+ assertLifecycleToken(operationId, "operationId");
212
+ const { kv, key } = coordinates(reg, binding), row = uncreatedFenceRow(reg, binding, operationId);
213
+ await createRowByteIdempotent(kv, key, row);
214
+ const created = await readNativeServiceGate(reg, binding);
215
+ if (!created)
216
+ throw new EpEnvelopeError("unavailable", "created service gate is not readable; retain the operation identity");
217
+ return created;
218
+ }
219
+ //# sourceMappingURL=native-service-gate.js.map