@sentropic/h2a-cli 0.27.0 → 0.28.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.
@@ -13,8 +13,8 @@
13
13
  *
14
14
  * Never throws on rejection; only the caller-supplied `applyRegistration` may.
15
15
  */
16
- import { type H2AActorRegistration, type H2AReplayGuard } from "@sentropic/h2a";
17
- export type H2AMirrorRejection = "malformed" | "not-mirror" | "no-signature" | "unauthorized-key" | "bad-signature" | "invalid-timestamp" | "expired" | "future" | "replayed" | "instance-key-mismatch";
16
+ import { type H2AActorRegistration, type H2AReplayGuard, type H2ASession } from "@sentropic/h2a";
17
+ export type H2AMirrorRejection = "malformed" | "not-mirror" | "no-signature" | "unauthorized-key" | "bad-signature" | "invalid-timestamp" | "expired" | "future" | "replayed" | "stale-sequence" | "instance-key-mismatch";
18
18
  export type H2AMirrorResult = {
19
19
  ok: true;
20
20
  applied: string[];
@@ -32,6 +32,18 @@ export interface AcceptMirrorOptions {
32
32
  guard: H2AReplayGuard;
33
33
  /** Apply an authorized registration to the local (remote-side) store. */
34
34
  applyRegistration: (registration: H2AActorRegistration) => void;
35
+ /**
36
+ * P2: apply a presence session (the impl RE-STAMPS heartbeatAt with the remote
37
+ * clock so freshness derives from the beat). Only called for sessions whose
38
+ * instance is owned by the verified key. Omit to ignore presence (P1 behavior).
39
+ */
40
+ applyPresence?: (session: H2ASession) => void;
41
+ /**
42
+ * P2 fencing: return true iff `seq` is strictly newer than the last applied
43
+ * for `signerInstance` (and record it). Return false to reject a stale/replayed
44
+ * beat. Omit to skip fencing (P1 behavior).
45
+ */
46
+ fenceSequence?: (signerInstance: string, seq: number) => boolean;
35
47
  /** Reference time (ms epoch) for the guard. Defaults to `Date.now()`. */
36
48
  now?: number;
37
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"accept.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/accept.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAGL,KAAK,oBAAoB,EAGzB,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,YAAY,GACZ,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,SAAS,GACT,QAAQ,GACR,UAAU,GACV,uBAAuB,CAAC;AAE5B,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAE9C,MAAM,WAAW,mBAAmB;IAClC,oGAAoG;IACpG,iBAAiB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACxD,oGAAoG;IACpG,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,oFAAoF;IACpF,KAAK,EAAE,cAAc,CAAC;IACtB,yEAAyE;IACzE,iBAAiB,EAAE,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChE,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,eAAe,CA+BpG"}
1
+ {"version":3,"file":"accept.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/accept.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAGL,KAAK,oBAAoB,EAGzB,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,YAAY,GACZ,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,SAAS,GACT,QAAQ,GACR,UAAU,GACV,gBAAgB,GAChB,uBAAuB,CAAC;AAE5B,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAE9C,MAAM,WAAW,mBAAmB;IAClC,oGAAoG;IACpG,iBAAiB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACxD,oGAAoG;IACpG,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,oFAAoF;IACpF,KAAK,EAAE,cAAc,CAAC;IACtB,yEAAyE;IACzE,iBAAiB,EAAE,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChE;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACjE,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,eAAe,CA8CpG"}
@@ -42,8 +42,22 @@ export function acceptMirrorEnvelope(payload, options) {
42
42
  const replay = options.guard.accept(envelope, options.now);
43
43
  if (!replay.ok)
44
44
  return { ok: false, reason: replay.reason };
45
+ // P2 monotonic fencing — after replay/freshness so a stale beat (new id, fresh
46
+ // window) still can't regress/resurrect state across a guard reset/restart.
47
+ if (typeof body.seq === "number" && options.fenceSequence) {
48
+ if (!options.fenceSequence(signer, body.seq))
49
+ return { ok: false, reason: "stale-sequence" };
50
+ }
45
51
  for (const reg of authorized)
46
52
  options.applyRegistration(reg);
53
+ // P2 presence — only sessions whose instance the verified key owns.
54
+ if (options.applyPresence && Array.isArray(body.presence)) {
55
+ const owned = new Set(authorized.map((r) => r.instance ?? r.id));
56
+ for (const session of body.presence) {
57
+ if (owned.has(session.instance))
58
+ options.applyPresence(session);
59
+ }
60
+ }
47
61
  return { ok: true, applied: authorized.map((r) => r.instance ?? r.id), signer };
48
62
  }
49
63
  //# sourceMappingURL=accept.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"accept.js","sourceRoot":"","sources":["../../../src/runtime/mirror/accept.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,aAAa,EACb,uBAAuB,EAKxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,oBAAoB,EAA8B,MAAM,YAAY,CAAC;AA+B9E,MAAM,UAAU,oBAAoB,CAAC,OAAgB,EAAE,OAA4B;IACjF,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACvE,MAAM,QAAQ,GAAG,OAA6C,CAAC;IAC/D,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACtF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;IACvC,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACxG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC9E,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,uBAAuB,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACrG,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAEhE,8EAA8E;IAC9E,4EAA4E;IAC5E,gEAAgE;IAChE,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAC1C,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC/E,CAAC;IACF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;IAEnF,MAAM,MAAM,GAAmB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3E,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAA4B,EAAE,CAAC;IAElF,KAAK,MAAM,GAAG,IAAI,UAAU;QAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAClF,CAAC"}
1
+ {"version":3,"file":"accept.js","sourceRoot":"","sources":["../../../src/runtime/mirror/accept.ts"],"names":[],"mappings":"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"}
@@ -8,18 +8,31 @@
8
8
  * `buildInstanceMirror` returns an UNSIGNED envelope — the caller signs it with
9
9
  * `signEnvelope` (DEC-116: possession of the key is the sole authority anchor).
10
10
  */
11
- import { type H2AActorRegistration, type H2AEnvelope } from "@sentropic/h2a";
12
- import type { LocalStore } from "../local-files/index.js";
11
+ import { type H2AActorRegistration, type H2AEnvelope, type H2ASession } from "@sentropic/h2a";
12
+ import { type LocalStore } from "../local-files/index.js";
13
13
  export declare const H2A_MIRROR_BODY_KIND: "mirror.instances";
14
14
  export interface H2AInstanceMirrorBody {
15
15
  readonly kind: typeof H2A_MIRROR_BODY_KIND;
16
16
  /** Append-only registration events. P1: the sender's own registration only. */
17
17
  readonly registrations: H2AActorRegistration[];
18
+ /**
19
+ * P2: the sender's live sessions. The remote RE-STAMPS `heartbeatAt` with its
20
+ * own clock on arrival (freshness is derived from the mirror beat, not the
21
+ * local clock — no ghost/skew/resurrection). Omitted in P1-only callers.
22
+ */
23
+ readonly presence?: H2ASession[];
24
+ /**
25
+ * P2: monotonic per-instance sequence (the CLI uses epoch ms — increases
26
+ * across restarts). The remote rejects a mirror with `seq <= last applied`
27
+ * (fencing), so a replayed older beat cannot resurrect stale presence.
28
+ */
29
+ readonly seq?: number;
18
30
  }
19
31
  /**
20
32
  * Build the unsigned mirror envelope for `instance` from the local store.
21
- * `nowMs` is injected (epoch ms) so the id + createdAt are deterministic in
22
- * tests; the CLI verb passes `Date.now()`.
33
+ * `nowMs` is injected (epoch ms) so the id + createdAt + seq are deterministic
34
+ * in tests; the CLI verb passes `Date.now()`. Includes the instance's own live
35
+ * sessions (P2) so the remote can derive its presence.
23
36
  */
24
37
  export declare function buildInstanceMirror(store: LocalStore, instance: string, nowMs: number): H2AEnvelope<H2AInstanceMirrorBody>;
25
38
  //# sourceMappingURL=build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAA6B,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,eAAO,MAAM,oBAAoB,EAAG,kBAA2B,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,OAAO,oBAAoB,CAAC;IAC3C,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,oBAAoB,EAAE,CAAC;CAChD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,WAAW,CAAC,qBAAqB,CAAC,CAapC"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAExE,eAAO,MAAM,oBAAoB,EAAG,kBAA2B,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,OAAO,oBAAoB,CAAC;IAC3C,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,oBAAoB,EAAE,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,WAAW,CAAC,qBAAqB,CAAC,CAgBpC"}
@@ -9,16 +9,19 @@
9
9
  * `signEnvelope` (DEC-116: possession of the key is the sole authority anchor).
10
10
  */
11
11
  import { H2A_PROTOCOL, H2A_VERSION } from "@sentropic/h2a";
12
+ import { listPresence } from "../local-files/index.js";
12
13
  export const H2A_MIRROR_BODY_KIND = "mirror.instances";
13
14
  /**
14
15
  * Build the unsigned mirror envelope for `instance` from the local store.
15
- * `nowMs` is injected (epoch ms) so the id + createdAt are deterministic in
16
- * tests; the CLI verb passes `Date.now()`.
16
+ * `nowMs` is injected (epoch ms) so the id + createdAt + seq are deterministic
17
+ * in tests; the CLI verb passes `Date.now()`. Includes the instance's own live
18
+ * sessions (P2) so the remote can derive its presence.
17
19
  */
18
20
  export function buildInstanceMirror(store, instance, nowMs) {
19
21
  const reg = store.findInstance(instance);
20
22
  if (!reg)
21
23
  throw new Error(`mirror: unknown local instance ${instance}`);
24
+ const presence = listPresence(store.paths.root, { now: nowMs }).filter((s) => s.instance === instance);
22
25
  return {
23
26
  protocol: H2A_PROTOCOL,
24
27
  version: H2A_VERSION,
@@ -26,7 +29,7 @@ export function buildInstanceMirror(store, instance, nowMs) {
26
29
  type: "event",
27
30
  actor: { instance, role: reg.roles?.[0] ?? "AGENTS", scope: "scope:default" },
28
31
  target: { instance },
29
- body: { kind: H2A_MIRROR_BODY_KIND, registrations: [reg] },
32
+ body: { kind: H2A_MIRROR_BODY_KIND, registrations: [reg], presence, seq: nowMs },
30
33
  createdAt: new Date(nowMs).toISOString()
31
34
  };
32
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/runtime/mirror/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAE,WAAW,EAA+C,MAAM,gBAAgB,CAAC;AAIxG,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAA2B,CAAC;AAQhE;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAiB,EACjB,QAAgB,EAChB,KAAa;IAEb,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAC;IACxE,OAAO;QACL,QAAQ,EAAE,YAAY;QACtB,OAAO,EAAE,WAAW;QACpB,EAAE,EAAE,UAAU,QAAQ,IAAI,KAAK,EAAE;QACjC,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE;QAC7E,MAAM,EAAE,EAAE,QAAQ,EAAE;QACpB,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE;QAC1D,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE;KACzC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/runtime/mirror/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,YAAY,EACZ,WAAW,EAIZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAmB,MAAM,yBAAyB,CAAC;AAExE,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAA2B,CAAC;AAoBhE;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAiB,EACjB,QAAgB,EAChB,KAAa;IAEb,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAC;IACxE,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CACpE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAC/B,CAAC;IACF,OAAO;QACL,QAAQ,EAAE,YAAY;QACtB,OAAO,EAAE,WAAW;QACpB,EAAE,EAAE,UAAU,QAAQ,IAAI,KAAK,EAAE;QACjC,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE;QAC7E,MAAM,EAAE,EAAE,QAAQ,EAAE;QACpB,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE;QAChF,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE;KACzC,CAAC;AACJ,CAAC"}
@@ -1,15 +1,6 @@
1
- /**
2
- * EVO-13 P1 — HTTP ingester for instance mirrors. A thin, channel-untrusting
3
- * front-end over `acceptMirrorEnvelope`: it reads a POSTed signed mirror and,
4
- * on success, applies the registration to the store via `registerInstance`.
5
- *
6
- * Runs as a SEPARATE deployment from the read-only MCP pod (it writes the store;
7
- * the MCP surface only reads it), co-mounting the RWX PVC. Store-agnostic +
8
- * unit-testable; the k8s wiring is the deploy kit.
9
- */
10
1
  import { type Server } from "node:http";
11
2
  import { type H2AReplayGuard } from "@sentropic/h2a";
12
- import type { LocalStore } from "../local-files/store.js";
3
+ import { type LocalStore } from "../local-files/index.js";
13
4
  import { type H2AMirrorRejection } from "./accept.js";
14
5
  export interface MirrorServerForStoreOptions {
15
6
  /** Operator-enrolled key PEMs allowed to mirror/bootstrap (out-of-band trust). */
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,2BAA2B;IAC1C,kFAAkF;IAClF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAmBxE;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,2BAAgC,GAAG,MAAM,CAmDzG"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/serve.ts"],"names":[],"mappings":"AAUA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAGtD,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,EAAgD,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACxG,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AA+B5E,MAAM,WAAW,2BAA2B;IAC1C,kFAAkF;IAClF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAmBxE;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,2BAAgC,GAAG,MAAM,CA2DzG"}
@@ -7,9 +7,43 @@
7
7
  * the MCP surface only reads it), co-mounting the RWX PVC. Store-agnostic +
8
8
  * unit-testable; the k8s wiring is the deploy kit.
9
9
  */
10
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
10
11
  import { createServer } from "node:http";
12
+ import { join } from "node:path";
11
13
  import { createReplayGuard } from "@sentropic/h2a";
14
+ import { localStorePaths, withLockSync, writePresence } from "../local-files/index.js";
12
15
  import { acceptMirrorEnvelope } from "./accept.js";
16
+ /**
17
+ * Durable, per-instance monotonic fence (P2). Returns a predicate that accepts
18
+ * `seq` iff it is strictly greater than the last recorded for `instance`, under
19
+ * a lock so concurrent beats from one agent can't race. Survives restarts (the
20
+ * in-memory replay guard does not), so a replayed older beat cannot resurrect
21
+ * stale presence after the ingester restarts.
22
+ */
23
+ function makeSequenceFence(root) {
24
+ const dir = join(localStorePaths(root).root, "identity");
25
+ const file = join(dir, "mirror-seq.json");
26
+ const lock = join(dir, ".mirror-seq.lock");
27
+ return (instance, seq) => {
28
+ mkdirSync(dir, { recursive: true });
29
+ return withLockSync(lock, () => {
30
+ let map = {};
31
+ try {
32
+ const parsed = JSON.parse(readFileSync(file, "utf8"));
33
+ if (parsed && typeof parsed === "object")
34
+ map = parsed;
35
+ }
36
+ catch {
37
+ map = {};
38
+ }
39
+ if (seq <= (map[instance] ?? 0))
40
+ return false;
41
+ map[instance] = seq;
42
+ writeFileSync(file, `${JSON.stringify(map)}\n`, "utf8");
43
+ return true;
44
+ });
45
+ };
46
+ }
13
47
  /** Map a mirror-pipeline rejection to an HTTP status code. */
14
48
  export function mirrorRejectionStatus(reason) {
15
49
  switch (reason) {
@@ -37,6 +71,8 @@ export function mirrorServerForStore(store, options = {}) {
37
71
  const enrolledKeys = options.enrolledKeys ?? [];
38
72
  const path = options.path ?? "/h2a/mirror";
39
73
  const maxBodyBytes = options.maxBodyBytes ?? 256 * 1024;
74
+ const root = store.paths.root;
75
+ const fenceSequence = makeSequenceFence(root);
40
76
  return createServer((req, res) => {
41
77
  const respond = (status, body) => {
42
78
  res.writeHead(status, { "content-type": "application/json" });
@@ -73,12 +109,17 @@ export function mirrorServerForStore(store, options = {}) {
73
109
  catch {
74
110
  return respond(400, { ok: false, error: "malformed" });
75
111
  }
112
+ const stampMs = options.now ? options.now() : Date.now();
76
113
  const result = acceptMirrorEnvelope(payload, {
77
114
  resolvePublicKeys: (signer) => store.listInstanceKeys(signer),
78
115
  enrolledKeys,
79
116
  guard,
80
117
  applyRegistration: (reg) => store.registerInstance(reg),
81
- ...(options.now ? { now: options.now() } : {})
118
+ // Re-stamp heartbeatAt with the REMOTE clock → freshness derives from the
119
+ // beat (no local-clock skew, no immortal ghost when the agent dies).
120
+ applyPresence: (session) => writePresence(root, { ...session, heartbeatAt: new Date(stampMs).toISOString(), state: "live" }),
121
+ fenceSequence,
122
+ now: stampMs
82
123
  });
83
124
  if (result.ok)
84
125
  return respond(202, { ok: true, applied: result.applied, signer: result.signer });
@@ -1 +1 @@
1
- {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/runtime/mirror/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAuB,MAAM,gBAAgB,CAAC;AAGxE,OAAO,EAAE,oBAAoB,EAA2B,MAAM,aAAa,CAAC;AAe5E,8DAA8D;AAC9D,MAAM,UAAU,qBAAqB,CAAC,MAA0B;IAC9D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW,CAAC;QACjB,KAAK,YAAY,CAAC;QAClB,KAAK,cAAc,CAAC;QACpB,KAAK,uBAAuB,CAAC;QAC7B,KAAK,mBAAmB;YACtB,OAAO,GAAG,CAAC;QACb,KAAK,kBAAkB,CAAC;QACxB,KAAK,eAAe;YAClB,OAAO,GAAG,CAAC;QACb,KAAK,UAAU;YACb,OAAO,GAAG,CAAC;QACb,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,GAAG,CAAC;QACb;YACE,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,oBAAoB,CAAC,KAAiB,EAAE,UAAuC,EAAE;IAC/F,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,iBAAiB,EAAE,CAAC;IACnD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,aAAa,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,GAAG,GAAG,IAAI,CAAC;IAExD,OAAO,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC/B,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,IAAa,EAAQ,EAAE;YACtD,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACnG,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/B,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,OAAO;gBAAE,OAAO;YACpB,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;YACtB,IAAI,KAAK,GAAG,YAAY,EAAE,CAAC;gBACzB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBACxD,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,OAAO;gBAAE,OAAO;YACpB,IAAI,OAAgB,CAAC;YACrB,IAAI,CAAC;gBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,EAAE;gBAC3C,iBAAiB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC;gBAC7D,YAAY;gBACZ,KAAK;gBACL,iBAAiB,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC;gBACvD,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/C,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,EAAE;gBAAE,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACjG,OAAO,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/runtime/mirror/serve.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentropic/h2a-cli",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "description": "Unified CLI surface for h2a hosts and MCP-oriented coordination flows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,7 +43,7 @@
43
43
  "@hono/mcp": "^0.3.0",
44
44
  "@hono/node-server": "^2.0.4",
45
45
  "@modelcontextprotocol/sdk": "^1.29.0",
46
- "@sentropic/h2a": "^0.27.0",
46
+ "@sentropic/h2a": "^0.28.0",
47
47
  "hono": "^4.12.23"
48
48
  },
49
49
  "publishConfig": {