@cotal-ai/workspace 0.50.0 → 0.51.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 (46) hide show
  1. package/dist/auth-paths.d.ts +50 -0
  2. package/dist/auth-paths.d.ts.map +1 -1
  3. package/dist/auth-paths.js +109 -1
  4. package/dist/auth-paths.js.map +1 -1
  5. package/dist/connect.d.ts +4 -1
  6. package/dist/connect.d.ts.map +1 -1
  7. package/dist/connect.js +7 -3
  8. package/dist/connect.js.map +1 -1
  9. package/dist/control-target.d.ts +1 -0
  10. package/dist/control-target.d.ts.map +1 -1
  11. package/dist/control-target.js +2 -0
  12. package/dist/control-target.js.map +1 -1
  13. package/dist/flags.d.ts +6 -2
  14. package/dist/flags.d.ts.map +1 -1
  15. package/dist/flags.js +10 -2
  16. package/dist/flags.js.map +1 -1
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/join-target.d.ts +173 -0
  22. package/dist/join-target.d.ts.map +1 -0
  23. package/dist/join-target.js +335 -0
  24. package/dist/join-target.js.map +1 -0
  25. package/dist/mesh-registry.d.ts +29 -5
  26. package/dist/mesh-registry.d.ts.map +1 -1
  27. package/dist/mesh-registry.js +64 -20
  28. package/dist/mesh-registry.js.map +1 -1
  29. package/dist/mesh-target.d.ts +2 -0
  30. package/dist/mesh-target.d.ts.map +1 -1
  31. package/dist/mesh-target.js +1 -0
  32. package/dist/mesh-target.js.map +1 -1
  33. package/dist/preflight.d.ts.map +1 -1
  34. package/dist/preflight.js +6 -0
  35. package/dist/preflight.js.map +1 -1
  36. package/dist/registration-policy.d.ts +69 -0
  37. package/dist/registration-policy.d.ts.map +1 -0
  38. package/dist/registration-policy.js +179 -0
  39. package/dist/registration-policy.js.map +1 -0
  40. package/dist/render.js +3 -3
  41. package/dist/render.js.map +1 -1
  42. package/dist/seat-checkpoint.d.ts +167 -0
  43. package/dist/seat-checkpoint.d.ts.map +1 -0
  44. package/dist/seat-checkpoint.js +413 -0
  45. package/dist/seat-checkpoint.js.map +1 -0
  46. package/package.json +2 -2
@@ -0,0 +1,179 @@
1
+ import { assertUserAuthInfo, findMesh, recordMesh } from "./mesh-registry.js";
2
+ import { isLoopbackHost } from "./join-target.js";
3
+ const bad = (message) => ({ ok: false, message });
4
+ const good = (value) => ({ ok: true, value });
5
+ /** Validate a user-auth bundle, fail-loud on every missing pin. The `userAuth` arm goes through
6
+ * {@link assertUserAuthInfo} — the same boundary every provider blob crosses — and additionally
7
+ * requires the pinned exchange URL: for a remote entry the endpoints are a trust position, not a
8
+ * convenience, because no local `up` exists to re-derive them. */
9
+ export function checkUserBundle(raw) {
10
+ let doc;
11
+ try {
12
+ doc = JSON.parse(raw);
13
+ }
14
+ catch {
15
+ return bad("✗ the user-auth bundle is not JSON - export it where the mesh runs and pass the file unmodified");
16
+ }
17
+ if (doc === null || typeof doc !== "object")
18
+ return bad("✗ the user-auth bundle must be a JSON object");
19
+ if (typeof doc.space !== "string" || !doc.space)
20
+ return bad("✗ the user-auth bundle names no space");
21
+ if (typeof doc.server !== "string" || !doc.server)
22
+ return bad("✗ the user-auth bundle names no broker server");
23
+ if (typeof doc.tlsRequired !== "boolean")
24
+ return bad("✗ the user-auth bundle must state tlsRequired explicitly (true or false) - transport strictness is part of what the export pins");
25
+ let policy;
26
+ if (doc.policy !== undefined) {
27
+ const value = doc.policy;
28
+ if (value === null || typeof value !== "object" || Array.isArray(value))
29
+ return bad("✗ the user-auth bundle policy must be an object with exactly policy.events = \"required\"");
30
+ const fields = Object.keys(value);
31
+ const extra = fields.find((key) => key !== "events");
32
+ if (extra)
33
+ return bad(`✗ the user-auth bundle policy has unsupported field \"policy.${extra}\"`);
34
+ if (value.events !== "required")
35
+ return bad('✗ the user-auth bundle policy.events must be exactly "required"');
36
+ policy = { events: "required" };
37
+ }
38
+ let userAuth;
39
+ try {
40
+ userAuth = assertUserAuthInfo(doc.userAuth);
41
+ }
42
+ catch (e) {
43
+ return bad(`✗ user-auth bundle: ${e.message}`);
44
+ }
45
+ if (!userAuth.endpoints?.url)
46
+ return bad("✗ the user-auth bundle pins no exchange endpoint (userAuth.endpoints.url) - for a remote registration that URL is trust, and it must come from the export, never be guessed");
47
+ if (userAuth.endpoints.agentProvisioningUrl !== undefined) {
48
+ // The provisioning endpoint receives the login bearer, so it rides the same pinned-fetch
49
+ // scheme rule as every other trust URL in this bundle: https, or a loopback http LITERAL.
50
+ let pu;
51
+ try {
52
+ pu = new URL(userAuth.endpoints.agentProvisioningUrl);
53
+ }
54
+ catch {
55
+ return bad("✗ the user-auth bundle's agent-provisioning endpoint (userAuth.endpoints.agentProvisioningUrl) is not a URL");
56
+ }
57
+ const refusal = assertPinnedFetchUrl(pu, "the bundle's agent-provisioning endpoint (userAuth.endpoints.agentProvisioningUrl)");
58
+ if (refusal)
59
+ return bad(refusal);
60
+ }
61
+ if (typeof doc.sentinelCreds !== "string" || !doc.sentinelCreds)
62
+ return bad("✗ the user-auth bundle carries no sentinelCreds - the sentinel identity is part of the export");
63
+ return good({ space: doc.space, server: doc.server, tlsRequired: doc.tlsRequired, userAuth, ...(policy ? { policy } : {}), sentinelCreds: doc.sentinelCreds });
64
+ }
65
+ /** Budget for the exchange trust probe — same posture as the mode probe above: run once, at
66
+ * registration, where patience is cheaper than a wrong record. */
67
+ const EXCHANGE_PROBE_TIMEOUT_MS = 5_000;
68
+ /**
69
+ * Fetch that CANNOT be walked off HTTPS.
70
+ *
71
+ * `fetch` follows redirects by default and will happily follow `https://` → `http://`, so a
72
+ * 302 from anyone on the path turns a pinned, encrypted fetch into a plaintext one — and the
73
+ * document being fetched IS the trust being adopted. `redirect: "manual"` stops the hop here;
74
+ * a redirect is then reported as the refusal it is, rather than silently followed.
75
+ *
76
+ * Loopback `http://` stays usable for tests and for an exchange on this machine (nothing leaves
77
+ * the box), which is also what keeps the suites honest without a TLS fixture. Everything else
78
+ * must be `https:`.
79
+ */
80
+ export function assertPinnedFetchUrl(u, what) {
81
+ if (u.protocol === "https:")
82
+ return undefined;
83
+ // The loopback exception is decided by PARSING the host as an address, never by how the text
84
+ // begins: `/^127\./` also matched `127.evil.com`, `127.0.0.1.nip.io` and `127.com`, which anyone
85
+ // can register, and it missed real spellings like `0177.0.0.1`. `isLoopbackHost` is the one
86
+ // authority for the question, canonicalization included. A name that does not parse as an IP is
87
+ // a NAME and gets no exception, however it starts — `localhost` included, since a hosts entry or
88
+ // a poisoned lookup can point it anywhere.
89
+ if (u.protocol === "http:" && isLoopbackHost(u.hostname))
90
+ return undefined;
91
+ // Name the ACTUAL rule. "must be https://" alone misleads the developer whose local flow used
92
+ // http://localhost: it blames the scheme, when the same scheme on 127.0.0.1 would have passed.
93
+ return (`✗ ${what} must be https:// (got ${u.protocol}//) - the pins this registration adopts cannot be fetched over a channel the network can rewrite` +
94
+ (u.protocol === "http:"
95
+ ? `. Plain http is accepted only for a loopback LITERAL (127.0.0.1, ::1), where nothing leaves this machine - "${u.hostname}" is a name, and a hosts entry or a poisoned lookup could point it anywhere, so use the literal`
96
+ : ""));
97
+ }
98
+ /** The pinned-fetch policy's verdict for ONE url, as data — so a suite can assert WHY a fetch was
99
+ * refused rather than only that something failed. A cert error, a timeout and a refused redirect
100
+ * are all "it did not work"; only this distinguishes them. Test seam, no production caller. */
101
+ export async function pinnedFetchProbe(target) {
102
+ try {
103
+ await pinnedFetch(target, "the pinned exchange");
104
+ return { refused: false, message: "" };
105
+ }
106
+ catch (e) {
107
+ return { refused: true, message: e.message };
108
+ }
109
+ }
110
+ /** One hop, no downgrade, no redirect-following. */
111
+ export async function pinnedFetch(target, what) {
112
+ const u = new URL(target);
113
+ const bad = assertPinnedFetchUrl(u, what);
114
+ if (bad)
115
+ throw new Error(bad);
116
+ const res = await fetch(u, { redirect: "manual", signal: AbortSignal.timeout(EXCHANGE_PROBE_TIMEOUT_MS) });
117
+ if (res.status >= 300 && res.status < 400)
118
+ throw new Error(`✗ ${what} answered ${res.status} (a redirect to ${JSON.stringify(res.headers.get("location") ?? "")}) - a redirect can move a pinned fetch onto plaintext or onto another host, so it is refused rather than followed; publish the document at the pinned URL itself`);
119
+ return res;
120
+ }
121
+ /** How long a trusted policy refresh stays warm. Pinned to the catalog freshness window by the
122
+ * user-bundle smoke, so the two cannot drift. */
123
+ export const POLICY_FRESH_MS = 5_000;
124
+ function sameRegistrationTrust(entry, bundle) {
125
+ const ua = entry.userAuth;
126
+ return entry.mode === "user" && ua !== undefined &&
127
+ entry.space === bundle.space && entry.server === bundle.server && (entry.tlsRequired === true) === bundle.tlsRequired &&
128
+ ua.idp.url === bundle.userAuth.idp.url && ua.idp.issuer === bundle.userAuth.idp.issuer &&
129
+ ua.idp.audience === bundle.userAuth.idp.audience && ua.endpoints?.url === bundle.userAuth.endpoints?.url;
130
+ }
131
+ /**
132
+ * The registration policy in force for a launch, a join, or a manager start on `target`.
133
+ *
134
+ * A manual user-auth registration made before policies existed learns its policy from its own
135
+ * pinned exchange: the same discovery document `meshes add --from` adopts, fetched with the same
136
+ * pinned rules, accepted only when every trust pin matches the recorded entry, and only `policy`
137
+ * is written. This runs where the policy is CONSUMED, after the command's own local refusals,
138
+ * never as a preparation step every command pays: a read-only `status` or `meshes` must not fail
139
+ * on an exchange that is down, and `supervise` must name a `--server` mismatch or a missing login
140
+ * before it dials anything. A refresh that fails once the warm window has expired refuses the
141
+ * operation, because the entry cannot say whether the space requires events.
142
+ */
143
+ export async function refreshRegistrationPolicy(target) {
144
+ const entry = findMesh(target.space);
145
+ if (!entry || entry.origin !== "manual" || entry.mode !== "user")
146
+ return target.policy;
147
+ if (entry.policy || !entry.userAuth?.endpoints?.url)
148
+ return entry.policy ?? target.policy;
149
+ const checkedAt = entry.policyCheckedAt ? Date.parse(entry.policyCheckedAt) : Number.NaN;
150
+ if (Number.isFinite(checkedAt) && Date.now() - checkedAt < POLICY_FRESH_MS)
151
+ return target.policy;
152
+ let base;
153
+ try {
154
+ base = new URL(entry.userAuth.endpoints.url);
155
+ }
156
+ catch {
157
+ throw new Error(`manual registration for "${entry.space}" has an invalid pinned exchange URL`);
158
+ }
159
+ base.pathname = `${base.pathname.replace(/\/$/, "")}/.well-known/cotal-mesh`;
160
+ base.search = "";
161
+ base.hash = "";
162
+ let response;
163
+ try {
164
+ response = await pinnedFetch(base.toString(), `manual registration "${entry.space}" policy refresh at ${entry.userAuth.endpoints.url}`);
165
+ }
166
+ catch (error) {
167
+ throw new Error(error.message.replace(/^✗ /, ""));
168
+ }
169
+ if (!response.ok)
170
+ throw new Error(`manual registration "${entry.space}" policy refresh at ${entry.userAuth.endpoints.url} answered HTTP ${response.status}`);
171
+ const checked = checkUserBundle(await response.text());
172
+ if (!checked.ok)
173
+ throw new Error(`manual registration "${entry.space}" policy refresh: ${checked.message.replace(/^✗ /, "")}`);
174
+ if (!sameRegistrationTrust(entry, checked.value))
175
+ throw new Error(`manual registration "${entry.space}" policy refresh returned different space, broker, transport, or user-auth trust pins`);
176
+ recordMesh({ ...entry, ...(checked.value.policy ? { policy: checked.value.policy } : {}), policyCheckedAt: new Date().toISOString() });
177
+ return checked.value.policy;
178
+ }
179
+ //# sourceMappingURL=registration-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration-policy.js","sourceRoot":"","sources":["../src/registration-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AACjH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIlD,MAAM,GAAG,GAAG,CAAC,OAAe,EAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AACxE,MAAM,IAAI,GAAG,CAAI,KAAQ,EAAY,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAc9D;;;mEAGmE;AACnE,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,GAAiD,CAAC;IACtD,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAU,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC,iGAAiG,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,8CAA8C,CAAC,CAAC;IACxG,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,KAAK;QAAE,OAAO,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACrG,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC/G,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC,iIAAiI,CAAC,CAAC;IACxL,IAAI,MAA4B,CAAC;IACjC,IAAK,GAA4B,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACvD,MAAM,KAAK,GAAI,GAA4B,CAAC,MAAM,CAAC;QACnD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACrE,OAAO,GAAG,CAAC,2FAA2F,CAAC,CAAC;QAC1G,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;QACrD,IAAI,KAAK;YAAE,OAAO,GAAG,CAAC,gEAAgE,KAAK,IAAI,CAAC,CAAC;QACjG,IAAK,KAA8B,CAAC,MAAM,KAAK,UAAU;YACvD,OAAO,GAAG,CAAC,iEAAiE,CAAC,CAAC;QAChF,MAAM,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAClC,CAAC;IACD,IAAI,QAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,GAAG,CAAC,uBAAwB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG;QAC1B,OAAO,GAAG,CAAC,6KAA6K,CAAC,CAAC;IAC5L,IAAI,QAAQ,CAAC,SAAS,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QAC1D,yFAAyF;QACzF,0FAA0F;QAC1F,IAAI,EAAO,CAAC;QACZ,IAAI,CAAC;YACH,EAAE,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,CAAC,6GAA6G,CAAC,CAAC;QAC5H,CAAC;QACD,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,EAAE,oFAAoF,CAAC,CAAC;QAC/H,IAAI,OAAO;YAAE,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,aAAa;QAC7D,OAAO,GAAG,CAAC,+FAA+F,CAAC,CAAC;IAC9G,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;AACjK,CAAC;AAED;mEACmE;AACnE,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAExC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,CAAM,EAAE,IAAY;IACvD,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC9C,6FAA6F;IAC7F,iGAAiG;IACjG,4FAA4F;IAC5F,gGAAgG;IAChG,iGAAiG;IACjG,2CAA2C;IAC3C,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3E,8FAA8F;IAC9F,+FAA+F;IAC/F,OAAO,CACL,KAAK,IAAI,0BAA0B,CAAC,CAAC,QAAQ,kGAAkG;QAC/I,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO;YACrB,CAAC,CAAC,+GAA+G,CAAC,CAAC,QAAQ,iGAAiG;YAC5N,CAAC,CAAC,EAAE,CAAC,CACR,CAAC;AACJ,CAAC;AAED;;gGAEgG;AAChG,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;QACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACzC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,IAAY;IAC5D,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,GAAG,GAAG,oBAAoB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAC3G,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG;QACvC,MAAM,IAAI,KAAK,CACb,KAAK,IAAI,aAAa,GAAG,CAAC,MAAM,mBAAmB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,kKAAkK,CACvQ,CAAC;IACJ,OAAO,GAAG,CAAC;AACb,CAAC;AAGD;kDACkD;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,SAAS,qBAAqB,CAAC,KAAgB,EAAE,MAAkB;IACjE,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC1B,OAAO,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,EAAE,KAAK,SAAS;QAC9C,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,KAAK,MAAM,CAAC,WAAW;QACrH,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM;QACtF,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;AAC7G,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,MAAuD;IACrG,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC;IACvF,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG;QAAE,OAAO,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC;IAC1F,MAAM,SAAS,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IACzF,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,eAAe;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC;IACjG,IAAI,IAAS,CAAC;IACd,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,KAAK,sCAAsC,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,yBAAyB,CAAC;IAC7E,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACjB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;IACf,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,wBAAwB,KAAK,CAAC,KAAK,uBAAuB,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1I,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAE,KAAe,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE;QACd,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,CAAC,KAAK,uBAAuB,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,kBAAkB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7I,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,CAAC,KAAK,qBAAqB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/H,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,CAAC,KAAK,uFAAuF,CAAC,CAAC;IAC9I,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,eAAe,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACvI,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;AAC9B,CAAC"}
package/dist/render.js CHANGED
@@ -42,7 +42,7 @@ function renderPreflightFailure(kind, t, pruned) {
42
42
  case "unreachable":
43
43
  // An operator-registered mesh usually runs on ANOTHER machine, so `cotal up` is the wrong
44
44
  // remedy here — this machine can only wait for it or stop pointing at it.
45
- if (t.origin === "manual")
45
+ if (t.origin === "manual" || t.origin === "catalog")
46
46
  return `✗ no broker answered at ${t.server} - "${t.space}" is registered here but its mesh is not up; start it where it runs, or \`cotal meshes rm ${t.space}\` to unregister it`;
47
47
  // An `up` / pre-origin record is KEPT on a liveness miss. Keep `no mesh running at`
48
48
  // so existing attach/mint cells still recognise the classified refusal, and name
@@ -52,11 +52,11 @@ function renderPreflightFailure(kind, t, pruned) {
52
52
  // machine only registered: the repair there is the credentials under `--root`, or re-registering
53
53
  // the entry — `cotal up` would start a DIFFERENT, local mesh under that name.
54
54
  case "registry-creds-rejected":
55
- return t.origin === "manual"
55
+ return t.origin === "manual" || t.origin === "catalog"
56
56
  ? `✗ mesh "${t.space}" at ${t.server} rejected the credentials under ${t.root} - re-mint them where that mesh runs, or re-register it with \`cotal meshes add ${t.space} --server <url> --root <dir> --force\``
57
57
  : `✗ mesh "${t.space}" at ${t.server} no longer matches its registry entry (credentials rejected - port reused?) - re-run \`cotal up\` from ${t.root}, or \`cotal meshes\` to see what's live`;
58
58
  case "registry-open-now-auth":
59
- return t.origin === "manual"
59
+ return t.origin === "manual" || t.origin === "catalog"
60
60
  ? `✗ "${t.space}" is registered as an open mesh, but the broker at ${t.server} requires auth - copy that mesh's account + creds under ${t.root} and re-register with \`cotal meshes add ${t.space} --server ${t.server} --mode auth --force\``
61
61
  : `✗ open mesh "${t.space}" at ${t.server} no longer matches its registry entry (broker now requires auth - port reused?) - re-run \`cotal up\` from ${t.root}, or \`cotal meshes\` to see what's live`;
62
62
  case "creds-rejected":
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ export declare const SEAT_CHECKPOINT_FORMAT: "cotal-seat-checkpoint/v1";
2
+ export declare const SEAT_CHECKPOINT_RECORD = "checkpoint.json";
3
+ /** The record is a bounded document like the resume document it carries, and for the same reason:
4
+ * a reader must be able to size its buffer before it trusts anything in the file. */
5
+ export declare const MAX_SEAT_CHECKPOINT_BYTES: number;
6
+ /**
7
+ * Where one cut's seat checkpoints live: `.cotal/maintenance/v<N>/checkpoints/<attempt>/<seat>/`.
8
+ *
9
+ * Scoped by the preservation attempt, not shared across cuts. The writer refuses a destination
10
+ * that already exists, which is what makes a checkpoint immutable once sealed; without the attempt
11
+ * in the path the second cut in a root would refuse on the first seat's leftover directory, and
12
+ * deleting the old one to make room would destroy the artifact a rollback still needs.
13
+ */
14
+ export declare function seatCheckpointDir(root: string, attemptId: string, version?: number): string;
15
+ /**
16
+ * Where a captured session file is put back on the destination.
17
+ *
18
+ * An anchor plus a relative path, never an absolute one. The destination's workspace root, account
19
+ * home and seat working tree are its own, and a record that carried the source host's absolute
20
+ * spelling would either miss them or write outside them.
21
+ */
22
+ export interface SeatCheckpointDestination {
23
+ readonly anchor: "workspace-root" | "home" | "cwd";
24
+ /** Relative to the anchor. No absolute spelling and no `..` segment, so a record cannot name a
25
+ * path outside the directory it is anchored on. */
26
+ readonly path: string;
27
+ }
28
+ /** One captured file, addressed by its name inside the checkpoint directory. */
29
+ export interface SeatCheckpointFile {
30
+ /** Basename within the checkpoint directory. Never a path, so a record cannot name a file
31
+ * outside the directory it was read from. */
32
+ readonly path: string;
33
+ readonly size: number;
34
+ readonly sha256: string;
35
+ readonly kind: "bundle" | "index-diff" | "worktree-diff" | "untracked" | "session-store" | "session-pointer";
36
+ /** Where a restore puts this file back. Carried by the two session kinds and by nothing else:
37
+ * the repository artifacts are consumed by git and tar rather than copied to a path. */
38
+ readonly restore?: SeatCheckpointDestination;
39
+ }
40
+ /** The repository half: a bundle anchored on a named base, plus the delta the bundle cannot carry. */
41
+ export interface SeatCheckpointRepository {
42
+ /** Full object id. A destination refuses a bundle that does not contain this commit. */
43
+ readonly base: string;
44
+ /** The exact selection rule the untracked set was produced under. A destination that cannot
45
+ * reproduce this rule refuses rather than restoring a silently thinner tree. */
46
+ readonly untrackedSelection: string;
47
+ /** `git status --porcelain` as the source read it, under the same selection rule: the untracked
48
+ * entries the rule excludes are excluded here too, so this describes the state the captured
49
+ * bytes can actually reproduce. A restore re-reads it in the promoted tree and refuses a
50
+ * difference, which is the only check that sees a restore that applied and still landed a
51
+ * different index. */
52
+ readonly status: string;
53
+ readonly bundle: SeatCheckpointFile;
54
+ readonly indexDiff: SeatCheckpointFile;
55
+ readonly worktreeDiff: SeatCheckpointFile;
56
+ readonly untracked: SeatCheckpointFile;
57
+ }
58
+ /** The harness half: an opaque file set plus the session id it is expected to reopen. Cotal does
59
+ * not parse a transcript, so the store travels as bytes and nothing here interprets it. */
60
+ export interface SeatCheckpointSession {
61
+ /** What `sessionContinuityClass` returned for this seat's connector. A destination refuses to
62
+ * promise more than the class allows. */
63
+ readonly continuity: "exact" | "fork" | "fresh" | "drain-only";
64
+ /** The harness-declared session id the store is expected to reopen, when the connector declares
65
+ * one. Absent for a class that does not reopen a session. */
66
+ readonly sessionId?: string;
67
+ /** The connector's session pointer file, captured beside the store. */
68
+ readonly pointer?: SeatCheckpointFile;
69
+ readonly store: readonly SeatCheckpointFile[];
70
+ }
71
+ /** The applied launch profile revision, so a destination can tell whether it is resuming the same
72
+ * intent rather than silently applying a newer profile to a recovered transcript. */
73
+ export interface SeatCheckpointProfile {
74
+ readonly configSha256: string;
75
+ readonly manifestSha256?: string;
76
+ readonly hash?: string;
77
+ }
78
+ export interface SeatCheckpoint<Entry = unknown> {
79
+ readonly format: typeof SEAT_CHECKPOINT_FORMAT;
80
+ /** The manager's resume entry, unchanged and first. The checkpoint restates none of it. */
81
+ readonly entry: Entry;
82
+ readonly space: string;
83
+ readonly name: string;
84
+ readonly lifecycleUid: string;
85
+ /** The per-seat writer generation this cut was taken at. A destination advances past it. */
86
+ readonly generation: number;
87
+ /** Absolute instant of the cut, compared against the destination's clock at gate 3. */
88
+ readonly capturedAt: string;
89
+ /** How long after `capturedAt` this checkpoint is admitted without an explicit override. A
90
+ * property of the deployment, stated here so a destination and an operator cannot disagree
91
+ * about what was promised. */
92
+ readonly recencyHorizonMs: number;
93
+ readonly profile: SeatCheckpointProfile;
94
+ readonly repository: SeatCheckpointRepository;
95
+ readonly session: SeatCheckpointSession;
96
+ }
97
+ /** Thrown by every refusal in this module. Each message names what the reader actually saw. */
98
+ export declare class SeatCheckpointError extends Error {
99
+ constructor(message: string);
100
+ }
101
+ export interface SeatCheckpointWriter {
102
+ readonly directory: string;
103
+ /** Copy one file into the checkpoint, returning its content address. `restore` is where the
104
+ * destination puts it back, required for a file a restore has to place rather than consume. */
105
+ captureFile(name: string, kind: SeatCheckpointFile["kind"], source: string, restore?: SeatCheckpointDestination): SeatCheckpointFile;
106
+ /** Write the record. Last, after every digest above was computed over bytes that landed. */
107
+ seal<Entry>(checkpoint: Omit<SeatCheckpoint<Entry>, "format">): SeatCheckpoint<Entry>;
108
+ /** Remove an unsealed directory this writer exclusively created. */
109
+ cleanup(): void;
110
+ }
111
+ /**
112
+ * Open a checkpoint destination. The disposition is `createArtifactWriter`'s in
113
+ * `implementations/cli/src/lib/backup-artifact.ts`: refuse a destination that already exists, and
114
+ * harden the directory to 0700 before anything lands in it.
115
+ */
116
+ export declare function createSeatCheckpointWriter(destination: string): SeatCheckpointWriter;
117
+ /** Parse a checkpoint record, refusing anything a gate would otherwise have to guess about. */
118
+ export declare function parseSeatCheckpoint(value: unknown): SeatCheckpoint;
119
+ /** Every file a checkpoint names, in one list, so gate 1 cannot miss one by walking the shape. */
120
+ export declare function seatCheckpointFiles(record: SeatCheckpoint): readonly SeatCheckpointFile[];
121
+ /** Read and parse the record itself, under the same discipline the resume document reader uses:
122
+ * no symlink, bounded read, and a re-stat after the read so a file that moved under us is a
123
+ * refusal rather than a value. */
124
+ export declare function readSeatCheckpoint(directory: string): SeatCheckpoint;
125
+ /**
126
+ * Gate 1, integrity. Every file the checkpoint names must be present, be a regular non-symlink
127
+ * file, match its recorded byte size, and match its recorded sha256. The file is re-stat'd after
128
+ * the read and a move is a refusal, which is the standard `readMaintenanceResumeDocument` holds
129
+ * itself to. Failure here is a refusal and no other gate is consulted.
130
+ */
131
+ export declare function assertSeatCheckpointIntegrity(directory: string, record: SeatCheckpoint): void;
132
+ export interface SeatIdentityAdmission {
133
+ /** The destination's own space. A checkpoint from another space is refused. */
134
+ readonly space: string;
135
+ /** Whether the recorded lifecycle uid belongs to a live incarnation here, judged by the caller
136
+ * from the same two sources `resumePreserved` uses: the manager-local retirement hold and the
137
+ * roster with the confirmed-predecessor exception. */
138
+ readonly lifecycleUidIsLive: boolean;
139
+ /** The destination's current profile revision for this seat, when it has one. */
140
+ readonly profileConfigSha256?: string;
141
+ }
142
+ /**
143
+ * Gate 2, identity. Authority, not usefulness: this gate has no override, which is the only reason
144
+ * gate 3 may have one.
145
+ */
146
+ export declare function assertSeatCheckpointIdentity(record: SeatCheckpoint, admission: SeatIdentityAdmission): void;
147
+ export interface SeatRecencyAdmission {
148
+ /** The destination's clock reading. Passed in so the decision is testable and so a caller that
149
+ * does not trust its clock can refuse before it gets here. */
150
+ readonly now: number;
151
+ /** Explicit operator consent to admit a checkpoint past its horizon, because a stale checkpoint
152
+ * is sometimes the only checkpoint. Recorded by the caller when it is used. */
153
+ readonly acceptStale?: boolean;
154
+ }
155
+ /** What gate 3 decided, so a caller can record an override that was actually exercised rather than
156
+ * one that was merely offered. */
157
+ export interface SeatRecencyVerdict {
158
+ readonly ageMs: number;
159
+ readonly admitted: "inside-horizon" | "override";
160
+ }
161
+ /**
162
+ * Gate 3, recency. Whether the transcript and the tree are close enough to the world for the
163
+ * resumed seat's next turn to be sensible. Refused by default outside the horizon, with all three
164
+ * values in the message; an explicit operator flag overrides and the caller records that it did.
165
+ */
166
+ export declare function admitSeatCheckpointRecency(record: SeatCheckpoint, admission: SeatRecencyAdmission): SeatRecencyVerdict;
167
+ //# sourceMappingURL=seat-checkpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seat-checkpoint.d.ts","sourceRoot":"","sources":["../src/seat-checkpoint.ts"],"names":[],"mappings":"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"}