@sentropic/h2a-cli 0.20.2 → 0.22.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.
- package/dist/bin.js +4 -1
- package/dist/bin.js.map +1 -1
- package/dist/cli-contract.d.ts.map +1 -1
- package/dist/cli-contract.js +20 -4
- package/dist/cli-contract.js.map +1 -1
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +266 -34
- package/dist/cli.js.map +1 -1
- package/dist/hosts/plugin.d.ts.map +1 -1
- package/dist/hosts/plugin.js +5 -1
- package/dist/hosts/plugin.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/runtime/drive/index.d.ts +72 -0
- package/dist/runtime/drive/index.d.ts.map +1 -0
- package/dist/runtime/drive/index.js +175 -0
- package/dist/runtime/drive/index.js.map +1 -0
- package/dist/runtime/drumbeat/inbox-relance.d.ts +29 -0
- package/dist/runtime/drumbeat/inbox-relance.d.ts.map +1 -0
- package/dist/runtime/drumbeat/inbox-relance.js +101 -0
- package/dist/runtime/drumbeat/inbox-relance.js.map +1 -0
- package/dist/runtime/drumbeat/index.d.ts +2 -1
- package/dist/runtime/drumbeat/index.d.ts.map +1 -1
- package/dist/runtime/drumbeat/index.js +2 -1
- package/dist/runtime/drumbeat/index.js.map +1 -1
- package/dist/runtime/drumbeat/relaunchers.d.ts +25 -1
- package/dist/runtime/drumbeat/relaunchers.d.ts.map +1 -1
- package/dist/runtime/drumbeat/relaunchers.js +53 -0
- package/dist/runtime/drumbeat/relaunchers.js.map +1 -1
- package/dist/runtime/drumbeat/scan.d.ts +2 -0
- package/dist/runtime/drumbeat/scan.d.ts.map +1 -1
- package/dist/runtime/drumbeat/scan.js +3 -0
- package/dist/runtime/drumbeat/scan.js.map +1 -1
- package/dist/runtime/drumbeat/watch.d.ts +3 -1
- package/dist/runtime/drumbeat/watch.d.ts.map +1 -1
- package/dist/runtime/drumbeat/watch.js +6 -2
- package/dist/runtime/drumbeat/watch.js.map +1 -1
- package/dist/runtime/identity/bindings.d.ts +60 -0
- package/dist/runtime/identity/bindings.d.ts.map +1 -0
- package/dist/runtime/identity/bindings.js +90 -0
- package/dist/runtime/identity/bindings.js.map +1 -0
- package/dist/runtime/identity/index.d.ts +10 -0
- package/dist/runtime/identity/index.d.ts.map +1 -0
- package/dist/runtime/identity/index.js +6 -0
- package/dist/runtime/identity/index.js.map +1 -0
- package/dist/runtime/identity/live.d.ts +26 -0
- package/dist/runtime/identity/live.d.ts.map +1 -0
- package/dist/runtime/identity/live.js +207 -0
- package/dist/runtime/identity/live.js.map +1 -0
- package/dist/runtime/identity/migration.d.ts +55 -0
- package/dist/runtime/identity/migration.d.ts.map +1 -0
- package/dist/runtime/identity/migration.js +100 -0
- package/dist/runtime/identity/migration.js.map +1 -0
- package/dist/runtime/identity/readers.d.ts +11 -0
- package/dist/runtime/identity/readers.d.ts.map +1 -0
- package/dist/runtime/identity/readers.js +114 -0
- package/dist/runtime/identity/readers.js.map +1 -0
- package/dist/runtime/identity/resolver.d.ts +50 -0
- package/dist/runtime/identity/resolver.d.ts.map +1 -0
- package/dist/runtime/identity/resolver.js +61 -0
- package/dist/runtime/identity/resolver.js.map +1 -0
- package/dist/runtime/local-files/store.d.ts.map +1 -1
- package/dist/runtime/local-files/store.js +19 -9
- package/dist/runtime/local-files/store.js.map +1 -1
- package/dist/runtime/mcp/handlers.d.ts +3 -1
- package/dist/runtime/mcp/handlers.d.ts.map +1 -1
- package/dist/runtime/mcp/handlers.js +2 -0
- package/dist/runtime/mcp/handlers.js.map +1 -1
- package/dist/runtime/mcp/sessions.d.ts +5 -1
- package/dist/runtime/mcp/sessions.d.ts.map +1 -1
- package/dist/runtime/mcp/sessions.js +2 -0
- package/dist/runtime/mcp/sessions.js.map +1 -1
- package/dist/runtime/mcp/stdio.d.ts +3 -0
- package/dist/runtime/mcp/stdio.d.ts.map +1 -1
- package/dist/runtime/mcp/stdio.js +4 -0
- package/dist/runtime/mcp/stdio.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/runtime/drumbeat/scan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,YAAY,EAAyB,MAAM,eAAe,CAAC;AAEpE,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/runtime/drumbeat/scan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,YAAY,EAAyB,MAAM,eAAe,CAAC;AAEpE,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAyB1C;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,UAA+B,EAAE;IAEjC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,wBAAwB,CAAC;IACpE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAyB,EAAE,CAAC;IAC1C,MAAM,SAAS,GAAuB,EAAE,CAAC;IACzC,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,SAAS;QACvC,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM;YAAE,SAAS;QAC1C,IAAI,KAAK,CAAC,QAAQ;YAAE,SAAS,CAAC,uDAAuD;QACrF,IAAI,KAAK,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC;YACtC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,KAAK,CAAC,UAAU,KAAK,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;YAC1E,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,YAAY,EAAE,KAAK,CAAC,YAAY;SACjC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -17,6 +17,8 @@ export interface H2ARelauncher {
|
|
|
17
17
|
/** A relauncher that only logs — the D2 default until real adapters land. */
|
|
18
18
|
export declare function loggingRelauncher(write: (line: string) => void): H2ARelauncher;
|
|
19
19
|
export interface DrumbeatTickOptions extends ScanDrumbeatOptions {
|
|
20
|
+
/** D4: optional pre-scan hook, used by watch to consume remote resume inboxes. */
|
|
21
|
+
beforeScan?: () => readonly string[] | Promise<readonly string[]>;
|
|
20
22
|
/** Hook for entries that hit the relance cap → escalate to PRINCIPAL (D7). */
|
|
21
23
|
onExhausted?: (entry: H2ADrumbeatEntry) => void | Promise<void>;
|
|
22
24
|
now?: number;
|
|
@@ -43,7 +45,7 @@ export interface DrumbeatWatchOptions extends DrumbeatTickOptions {
|
|
|
43
45
|
intervalMs?: number;
|
|
44
46
|
/** Stop the loop. */
|
|
45
47
|
signal?: AbortSignal;
|
|
46
|
-
onTick?: (result: DrumbeatTickResult) => void
|
|
48
|
+
onTick?: (result: DrumbeatTickResult) => void | Promise<void>;
|
|
47
49
|
}
|
|
48
50
|
/**
|
|
49
51
|
* Run the drumbeat loop until `signal` aborts. Each beat: scan → relance via
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/runtime/drumbeat/watch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAsB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,EAAgB,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,aAAa,CAS9E;AAED,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnG,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnG;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,0EAA0E;AAC1E,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/runtime/drumbeat/watch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAsB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,EAAgB,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,aAAa,CAS9E;AAED,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAClE,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnG,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnG;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,0EAA0E;AAC1E,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CA8D7B;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAiBD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAQf"}
|
|
@@ -19,7 +19,11 @@ export function loggingRelauncher(write) {
|
|
|
19
19
|
}
|
|
20
20
|
/** One scan→dispatch pass (no timers) — the testable unit of the loop. */
|
|
21
21
|
export async function drumbeatTick(root, relauncher, options = {}) {
|
|
22
|
-
const
|
|
22
|
+
const preRelanced = await options.beforeScan?.();
|
|
23
|
+
const { findings, exhausted } = scanDrumbeat(root, {
|
|
24
|
+
maxRelances: options.maxRelances,
|
|
25
|
+
skipInstances: [...(options.skipInstances ?? []), ...(preRelanced ?? [])]
|
|
26
|
+
});
|
|
23
27
|
const relanced = [];
|
|
24
28
|
const k = options.deciderAfter ?? 1;
|
|
25
29
|
for (const finding of findings) {
|
|
@@ -98,7 +102,7 @@ export async function runDrumbeatWatch(root, relauncher, options = {}) {
|
|
|
98
102
|
const intervalMs = options.intervalMs ?? 30_000;
|
|
99
103
|
while (!options.signal?.aborted) {
|
|
100
104
|
const result = await drumbeatTick(root, relauncher, options);
|
|
101
|
-
options.onTick?.(result);
|
|
105
|
+
await options.onTick?.(result);
|
|
102
106
|
if (options.signal?.aborted)
|
|
103
107
|
break;
|
|
104
108
|
await delay(intervalMs, options.signal);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../../src/runtime/drumbeat/watch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,YAAY,EAAqD,MAAM,WAAW,CAAC;AAC5F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,EAErB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAQxD,6EAA6E;AAC7E,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,OAAO;QACL,OAAO,CAAC,OAAO;YACb,KAAK,CACH,2BAA2B,OAAO,CAAC,QAAQ,YAAY,OAAO,CAAC,MAAM,WAAW,OAAO,CAAC,YAAY,GAAG,CACxG,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../../src/runtime/drumbeat/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity binding registry + proof-of-possession (DEC-116, F1 — the
|
|
3
|
+
* load-bearing security fix).
|
|
4
|
+
*
|
|
5
|
+
* Reconnect de-collision binds `(host, providerSessionId, workspaceId)` → the
|
|
6
|
+
* agent's perennial identity. **RECLAIM requires proof-of-possession**: the
|
|
7
|
+
* connector must sign a fresh nonce with the ed25519 key already bound to that
|
|
8
|
+
* identity (verified against the instance's active keys). The provider session
|
|
9
|
+
* id is a spoofable *routing hint* — never the authenticator. No valid
|
|
10
|
+
* signature → **MINT** a fresh identity (so a process presenting a victim's
|
|
11
|
+
* id/workspace, without the key, gets a new identity, not the victim's inbox).
|
|
12
|
+
* The read → decide → append runs in ONE lock (no reclaim/mint race, F3).
|
|
13
|
+
*/
|
|
14
|
+
import { type H2ASignature } from "@sentropic/h2a";
|
|
15
|
+
export interface H2AIdentityBinding {
|
|
16
|
+
readonly host: string;
|
|
17
|
+
readonly providerSessionId: string;
|
|
18
|
+
readonly workspaceId: string;
|
|
19
|
+
/** The addressable handle `host:label:uuid12` — what the keyring + addressing key on. */
|
|
20
|
+
readonly instance: string;
|
|
21
|
+
/** The perennial agent UUID (its first 12 hex form `uuid12` in the instance). */
|
|
22
|
+
readonly agentUuid: string;
|
|
23
|
+
readonly at: string;
|
|
24
|
+
}
|
|
25
|
+
export interface IdentityBindingKey {
|
|
26
|
+
readonly host: string;
|
|
27
|
+
readonly providerSessionId: string;
|
|
28
|
+
readonly workspaceId: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function listBindings(root: string): H2AIdentityBinding[];
|
|
31
|
+
/** The latest binding matching the key (append-only → last wins), or undefined. */
|
|
32
|
+
export declare function findBinding(root: string, key: IdentityBindingKey): H2AIdentityBinding | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Verify a reclaim proof: `signature` over `nonce` must verify against ANY of
|
|
35
|
+
* the agent's active public keys. Total — never throws.
|
|
36
|
+
*/
|
|
37
|
+
export declare function verifyReclaimProof(nonce: string, signature: H2ASignature, publicKeys: readonly string[]): boolean;
|
|
38
|
+
export interface ReclaimOrMintDeps {
|
|
39
|
+
/** PoP: true iff the connector proved possession of the bound instance's key. */
|
|
40
|
+
verifyProof(binding: H2AIdentityBinding): boolean;
|
|
41
|
+
/** Mint a fresh identity (new uuid + derived instance) when no reclaim. */
|
|
42
|
+
mint(): {
|
|
43
|
+
instance: string;
|
|
44
|
+
agentUuid: string;
|
|
45
|
+
};
|
|
46
|
+
now(): number;
|
|
47
|
+
}
|
|
48
|
+
export interface ReclaimOrMintResult {
|
|
49
|
+
readonly action: "reclaim" | "mint";
|
|
50
|
+
readonly instance: string;
|
|
51
|
+
readonly agentUuid: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Atomically (one lock) reclaim the existing binding iff it exists AND
|
|
55
|
+
* proof-of-possession passes; otherwise mint a fresh identity and record the new
|
|
56
|
+
* binding. Spoofing the id without the key → mint (a new identity), never a
|
|
57
|
+
* reclaim of someone else's.
|
|
58
|
+
*/
|
|
59
|
+
export declare function reclaimOrMint(root: string, key: IdentityBindingKey, deps: ReclaimOrMintDeps): ReclaimOrMintResult;
|
|
60
|
+
//# sourceMappingURL=bindings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/bindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAYD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAa/D;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,kBAAkB,GAAG,SAAS,CAYjG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,YAAY,EACvB,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAST;AAED,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC;IAClD,2EAA2E;IAC3E,IAAI,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,GAAG,IAAI,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,iBAAiB,GACtB,mBAAmB,CAerB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity binding registry + proof-of-possession (DEC-116, F1 — the
|
|
3
|
+
* load-bearing security fix).
|
|
4
|
+
*
|
|
5
|
+
* Reconnect de-collision binds `(host, providerSessionId, workspaceId)` → the
|
|
6
|
+
* agent's perennial identity. **RECLAIM requires proof-of-possession**: the
|
|
7
|
+
* connector must sign a fresh nonce with the ed25519 key already bound to that
|
|
8
|
+
* identity (verified against the instance's active keys). The provider session
|
|
9
|
+
* id is a spoofable *routing hint* — never the authenticator. No valid
|
|
10
|
+
* signature → **MINT** a fresh identity (so a process presenting a victim's
|
|
11
|
+
* id/workspace, without the key, gets a new identity, not the victim's inbox).
|
|
12
|
+
* The read → decide → append runs in ONE lock (no reclaim/mint race, F3).
|
|
13
|
+
*/
|
|
14
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { verifyCanonical } from "@sentropic/h2a";
|
|
17
|
+
import { localStorePaths, withLockSync } from "../local-files/index.js";
|
|
18
|
+
function identityDir(root) {
|
|
19
|
+
return join(localStorePaths(root).root, "identity");
|
|
20
|
+
}
|
|
21
|
+
function bindingsFile(root) {
|
|
22
|
+
return join(identityDir(root), "bindings.jsonl");
|
|
23
|
+
}
|
|
24
|
+
function bindingsLock(root) {
|
|
25
|
+
return join(identityDir(root), ".lock");
|
|
26
|
+
}
|
|
27
|
+
export function listBindings(root) {
|
|
28
|
+
const f = bindingsFile(root);
|
|
29
|
+
if (!existsSync(f))
|
|
30
|
+
return [];
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const line of readFileSync(f, "utf8").split("\n")) {
|
|
33
|
+
if (!line.trim())
|
|
34
|
+
continue;
|
|
35
|
+
try {
|
|
36
|
+
out.push(JSON.parse(line));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// skip malformed
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
/** The latest binding matching the key (append-only → last wins), or undefined. */
|
|
45
|
+
export function findBinding(root, key) {
|
|
46
|
+
let found;
|
|
47
|
+
for (const b of listBindings(root)) {
|
|
48
|
+
if (b.host === key.host &&
|
|
49
|
+
b.providerSessionId === key.providerSessionId &&
|
|
50
|
+
b.workspaceId === key.workspaceId) {
|
|
51
|
+
found = b;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return found;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Verify a reclaim proof: `signature` over `nonce` must verify against ANY of
|
|
58
|
+
* the agent's active public keys. Total — never throws.
|
|
59
|
+
*/
|
|
60
|
+
export function verifyReclaimProof(nonce, signature, publicKeys) {
|
|
61
|
+
for (const pem of publicKeys) {
|
|
62
|
+
try {
|
|
63
|
+
if (verifyCanonical(nonce, signature, pem))
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// try the next active key
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Atomically (one lock) reclaim the existing binding iff it exists AND
|
|
74
|
+
* proof-of-possession passes; otherwise mint a fresh identity and record the new
|
|
75
|
+
* binding. Spoofing the id without the key → mint (a new identity), never a
|
|
76
|
+
* reclaim of someone else's.
|
|
77
|
+
*/
|
|
78
|
+
export function reclaimOrMint(root, key, deps) {
|
|
79
|
+
mkdirSync(identityDir(root), { recursive: true });
|
|
80
|
+
return withLockSync(bindingsLock(root), () => {
|
|
81
|
+
const existing = findBinding(root, key);
|
|
82
|
+
if (existing && deps.verifyProof(existing)) {
|
|
83
|
+
return { action: "reclaim", instance: existing.instance, agentUuid: existing.agentUuid };
|
|
84
|
+
}
|
|
85
|
+
const minted = deps.mint();
|
|
86
|
+
appendFileSync(bindingsFile(root), `${JSON.stringify({ ...key, instance: minted.instance, agentUuid: minted.agentUuid, at: new Date(deps.now()).toISOString() })}\n`, "utf8");
|
|
87
|
+
return { action: "mint", instance: minted.instance, agentUuid: minted.agentUuid };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=bindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindings.js","sourceRoot":"","sources":["../../../src/runtime/identity/bindings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { resolveProviderSession } from "./resolver.js";
|
|
2
|
+
export type { ProviderSession, ProviderSessionReaders, ProviderSessionSource, ResolveProviderSessionInput } from "./resolver.js";
|
|
3
|
+
export { defaultProviderSessionReaders } from "./readers.js";
|
|
4
|
+
export { listBindings, findBinding, verifyReclaimProof, reclaimOrMint } from "./bindings.js";
|
|
5
|
+
export type { H2AIdentityBinding, IdentityBindingKey, ReclaimOrMintDeps, ReclaimOrMintResult } from "./bindings.js";
|
|
6
|
+
export { mergeInboxDedup, decideLegacyAdoption, listIdentityAliases, legacyAliasAlreadyAdopted, recordIdentityAlias } from "./migration.js";
|
|
7
|
+
export type { H2AIdentityAlias, LegacyAdoptionInput, LegacyAdoptionDecision } from "./migration.js";
|
|
8
|
+
export { resolveLiveIdentity } from "./live.js";
|
|
9
|
+
export type { ResolveLiveIdentityInput, ResolvedLiveIdentity } from "./live.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,YAAY,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { resolveProviderSession } from "./resolver.js";
|
|
2
|
+
export { defaultProviderSessionReaders } from "./readers.js";
|
|
3
|
+
export { listBindings, findBinding, verifyReclaimProof, reclaimOrMint } from "./bindings.js";
|
|
4
|
+
export { mergeInboxDedup, decideLegacyAdoption, listIdentityAliases, legacyAliasAlreadyAdopted, recordIdentityAlias } from "./migration.js";
|
|
5
|
+
export { resolveLiveIdentity } from "./live.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/identity/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAOvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AAOvB,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type H2AWorkspaceRef } from "@sentropic/h2a";
|
|
2
|
+
import { type ProviderSessionReaders } from "./resolver.js";
|
|
3
|
+
export interface ResolveLiveIdentityInput {
|
|
4
|
+
readonly root: string;
|
|
5
|
+
readonly host: string;
|
|
6
|
+
readonly cwd: string;
|
|
7
|
+
readonly explicitInstance?: string;
|
|
8
|
+
readonly name?: string;
|
|
9
|
+
readonly scopes?: readonly string[];
|
|
10
|
+
readonly readers?: ProviderSessionReaders;
|
|
11
|
+
readonly now?: () => number;
|
|
12
|
+
}
|
|
13
|
+
export interface ResolvedLiveIdentity {
|
|
14
|
+
readonly instance: string;
|
|
15
|
+
readonly host: string;
|
|
16
|
+
readonly workspace?: H2AWorkspaceRef;
|
|
17
|
+
readonly name?: string;
|
|
18
|
+
readonly legacyInstance?: string;
|
|
19
|
+
readonly action: "override" | "reclaim" | "mint";
|
|
20
|
+
readonly providerSessionSource?: string;
|
|
21
|
+
readonly privateKeyPath?: string;
|
|
22
|
+
readonly publicKeyPath?: string;
|
|
23
|
+
readonly migrationNotice?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function resolveLiveIdentity(input: ResolveLiveIdentityInput): ResolvedLiveIdentity;
|
|
26
|
+
//# sourceMappingURL=live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/live.ts"],"names":[],"mappings":"AAYA,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEpF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IACjD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AA6ID,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,oBAAoB,CA2FzF"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { createHash, generateKeyPairSync } from "node:crypto";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { hostname } from "node:os";
|
|
4
|
+
import { basename, join } from "node:path";
|
|
5
|
+
import { deriveInstanceId, deriveWorkspaceId, mintAgentUuid, signCanonical } from "@sentropic/h2a";
|
|
6
|
+
import { createLocalStore } from "../local-files/store.js";
|
|
7
|
+
import { findBinding, reclaimOrMint, verifyReclaimProof } from "./bindings.js";
|
|
8
|
+
import { decideLegacyAdoption, legacyAliasAlreadyAdopted, recordIdentityAlias } from "./migration.js";
|
|
9
|
+
import { defaultProviderSessionReaders } from "./readers.js";
|
|
10
|
+
import { resolveProviderSession } from "./resolver.js";
|
|
11
|
+
function safeKeyName(instance) {
|
|
12
|
+
return instance.replace(/[:/]/g, "-");
|
|
13
|
+
}
|
|
14
|
+
function keyPaths(root, instance) {
|
|
15
|
+
const keysDir = join(root, "keys");
|
|
16
|
+
return {
|
|
17
|
+
privateKeyPath: join(keysDir, `${safeKeyName(instance)}.key.pem`),
|
|
18
|
+
publicKeyPath: join(keysDir, `${safeKeyName(instance)}.pub.pem`)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function readMachineId() {
|
|
22
|
+
for (const path of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
23
|
+
try {
|
|
24
|
+
const id = readFileSync(path, "utf8").trim();
|
|
25
|
+
if (id.length > 0)
|
|
26
|
+
return id;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// try the next source
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return hostname() || "unknown-machine";
|
|
33
|
+
}
|
|
34
|
+
function realWorkspacePath(cwd) {
|
|
35
|
+
try {
|
|
36
|
+
return realpathSync(cwd);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return cwd;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function labelFromCwd(cwd) {
|
|
43
|
+
return basename(cwd) || "workspace";
|
|
44
|
+
}
|
|
45
|
+
function publicKeyFingerprint(publicKeyPem) {
|
|
46
|
+
return createHash("sha256").update(publicKeyPem, "utf8").digest("hex").slice(0, 16);
|
|
47
|
+
}
|
|
48
|
+
function generateKeypair() {
|
|
49
|
+
const { privateKey, publicKey } = generateKeyPairSync("ed25519");
|
|
50
|
+
return {
|
|
51
|
+
privateKeyPem: privateKey.export({ format: "pem", type: "pkcs8" }).toString(),
|
|
52
|
+
publicKeyPem: publicKey.export({ format: "pem", type: "spki" }).toString()
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function readKeypair(root, instance) {
|
|
56
|
+
const paths = keyPaths(root, instance);
|
|
57
|
+
if (!existsSync(paths.privateKeyPath) || !existsSync(paths.publicKeyPath))
|
|
58
|
+
return undefined;
|
|
59
|
+
return {
|
|
60
|
+
privateKeyPem: readFileSync(paths.privateKeyPath, "utf8"),
|
|
61
|
+
publicKeyPem: readFileSync(paths.publicKeyPath, "utf8"),
|
|
62
|
+
...paths
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function ensureKeypair(root, instance, adoptFromInstance) {
|
|
66
|
+
const existing = readKeypair(root, instance);
|
|
67
|
+
if (existing) {
|
|
68
|
+
return {
|
|
69
|
+
publicKeyPem: existing.publicKeyPem,
|
|
70
|
+
privateKeyPath: existing.privateKeyPath,
|
|
71
|
+
publicKeyPath: existing.publicKeyPath
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const paths = keyPaths(root, instance);
|
|
75
|
+
mkdirSync(join(root, "keys"), { recursive: true });
|
|
76
|
+
const adopted = adoptFromInstance ? readKeypair(root, adoptFromInstance) : undefined;
|
|
77
|
+
if (adopted) {
|
|
78
|
+
copyFileSync(adopted.privateKeyPath, paths.privateKeyPath);
|
|
79
|
+
copyFileSync(adopted.publicKeyPath, paths.publicKeyPath);
|
|
80
|
+
return { publicKeyPem: adopted.publicKeyPem, ...paths };
|
|
81
|
+
}
|
|
82
|
+
const generated = generateKeypair();
|
|
83
|
+
writeFileSync(paths.privateKeyPath, generated.privateKeyPem, { encoding: "utf8", mode: 0o600 });
|
|
84
|
+
writeFileSync(paths.publicKeyPath, generated.publicKeyPem, "utf8");
|
|
85
|
+
return { publicKeyPem: generated.publicKeyPem, ...paths };
|
|
86
|
+
}
|
|
87
|
+
function provesLocalKey(root, instance) {
|
|
88
|
+
const store = createLocalStore({ root });
|
|
89
|
+
const keypair = readKeypair(root, instance);
|
|
90
|
+
if (!keypair)
|
|
91
|
+
return false;
|
|
92
|
+
const activeKeys = store.listInstanceKeys(instance);
|
|
93
|
+
if (activeKeys.length === 0)
|
|
94
|
+
return false;
|
|
95
|
+
const nonce = `identity-reclaim:${instance}:${publicKeyFingerprint(keypair.publicKeyPem)}`;
|
|
96
|
+
try {
|
|
97
|
+
const signature = signCanonical(nonce, { by: instance, privateKeyPem: keypair.privateKeyPem });
|
|
98
|
+
return verifyReclaimProof(nonce, signature, activeKeys);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function ensureRegistered(input) {
|
|
105
|
+
const store = createLocalStore({ root: input.root });
|
|
106
|
+
const existing = store.findInstance(input.instance);
|
|
107
|
+
if (!existing) {
|
|
108
|
+
const registration = {
|
|
109
|
+
id: input.instance,
|
|
110
|
+
instance: input.instance,
|
|
111
|
+
roles: ["AGENTS"],
|
|
112
|
+
scopes: [...input.scopes],
|
|
113
|
+
capabilities: [],
|
|
114
|
+
endpoints: [{ kind: "local-files", uri: `file://${input.root}` }],
|
|
115
|
+
publicKeys: [input.publicKeyPem],
|
|
116
|
+
acceptedPolicies: [],
|
|
117
|
+
agentUuid: input.agentUuid,
|
|
118
|
+
workspace: input.workspace,
|
|
119
|
+
name: input.name,
|
|
120
|
+
createdAt: new Date(input.now()).toISOString()
|
|
121
|
+
};
|
|
122
|
+
store.registerInstance(registration);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (!store.listInstanceKeys(input.instance).includes(input.publicKeyPem)) {
|
|
126
|
+
store.addInstanceKey(input.instance, input.publicKeyPem);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export function resolveLiveIdentity(input) {
|
|
130
|
+
const host = input.host || "agent";
|
|
131
|
+
const label = labelFromCwd(input.cwd);
|
|
132
|
+
const name = input.name ?? label;
|
|
133
|
+
if (input.explicitInstance) {
|
|
134
|
+
return { instance: input.explicitInstance, host, action: "override" };
|
|
135
|
+
}
|
|
136
|
+
const readers = input.readers ?? defaultProviderSessionReaders;
|
|
137
|
+
const provider = resolveProviderSession({ host, cwd: input.cwd, readers });
|
|
138
|
+
const realPath = realWorkspacePath(input.cwd);
|
|
139
|
+
const workspaceId = provider.workspaceHint ??
|
|
140
|
+
deriveWorkspaceId({ machineId: readMachineId(), path: realPath });
|
|
141
|
+
const workspace = {
|
|
142
|
+
id: workspaceId,
|
|
143
|
+
path: realPath,
|
|
144
|
+
host,
|
|
145
|
+
label
|
|
146
|
+
};
|
|
147
|
+
const legacyInstance = `${host}:${label}`;
|
|
148
|
+
const now = input.now ?? Date.now;
|
|
149
|
+
const scopes = input.scopes?.length ? input.scopes : ["scope:default"];
|
|
150
|
+
const mint = () => {
|
|
151
|
+
const agentUuid = mintAgentUuid();
|
|
152
|
+
return {
|
|
153
|
+
agentUuid,
|
|
154
|
+
instance: deriveInstanceId({ host, label: name, uuid: agentUuid })
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
const providerSessionId = provider.providerSessionId ?? `fallback:${host}:${workspace.id}:${Date.now()}`;
|
|
158
|
+
const result = host === "remote"
|
|
159
|
+
? { action: "mint", ...mint() }
|
|
160
|
+
: reclaimOrMint(input.root, { host, providerSessionId, workspaceId: workspace.id }, {
|
|
161
|
+
verifyProof: (binding) => provesLocalKey(input.root, binding.instance),
|
|
162
|
+
mint,
|
|
163
|
+
now
|
|
164
|
+
});
|
|
165
|
+
const existingBinding = findBinding(input.root, {
|
|
166
|
+
host,
|
|
167
|
+
providerSessionId,
|
|
168
|
+
workspaceId: workspace.id
|
|
169
|
+
});
|
|
170
|
+
const legacyDecision = decideLegacyAdoption({
|
|
171
|
+
legacyAlreadyAdopted: legacyAliasAlreadyAdopted(input.root, legacyInstance),
|
|
172
|
+
provedLegacyPossession: provesLocalKey(input.root, legacyInstance)
|
|
173
|
+
});
|
|
174
|
+
const adoptedFrom = result.action === "mint" && legacyDecision.adopt ? legacyInstance : undefined;
|
|
175
|
+
const keypair = ensureKeypair(input.root, result.instance, adoptedFrom);
|
|
176
|
+
ensureRegistered({
|
|
177
|
+
root: input.root,
|
|
178
|
+
instance: result.instance,
|
|
179
|
+
agentUuid: result.agentUuid,
|
|
180
|
+
workspace,
|
|
181
|
+
name,
|
|
182
|
+
publicKeyPem: keypair.publicKeyPem,
|
|
183
|
+
scopes,
|
|
184
|
+
now
|
|
185
|
+
});
|
|
186
|
+
recordIdentityAlias(input.root, {
|
|
187
|
+
instance: result.instance,
|
|
188
|
+
legacyInstance,
|
|
189
|
+
adoptedKeyring: Boolean(adoptedFrom),
|
|
190
|
+
at: new Date(now()).toISOString()
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
instance: result.instance,
|
|
194
|
+
host,
|
|
195
|
+
workspace,
|
|
196
|
+
name,
|
|
197
|
+
legacyInstance,
|
|
198
|
+
action: result.action,
|
|
199
|
+
providerSessionSource: provider.source,
|
|
200
|
+
privateKeyPath: keypair.privateKeyPath,
|
|
201
|
+
publicKeyPath: keypair.publicKeyPath,
|
|
202
|
+
migrationNotice: result.action === "mint" || !existingBinding
|
|
203
|
+
? `identity migration: ${result.instance} reads legacy ${legacyInstance}; ${legacyDecision.reason}`
|
|
204
|
+
: undefined
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../../src/runtime/identity/live.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transparent migration dual-read (DEC-116).
|
|
3
|
+
*
|
|
4
|
+
* After the identity fix, an agent's perennial inbox lives under its new
|
|
5
|
+
* uuid-bearing instance id, while messages addressed before the migration sit
|
|
6
|
+
* under the old label-derived instance dir(s). Migration must be transparent
|
|
7
|
+
* and immediate: the agent keeps receiving everything with no manual move. The
|
|
8
|
+
* read path therefore unions the current inbox with one or more legacy inbox
|
|
9
|
+
* locations, deduplicated by envelope id — equivalent to reading several dirs
|
|
10
|
+
* as if they were one (same id-sorted order as the single-dir reader).
|
|
11
|
+
*
|
|
12
|
+
* Pure + total: the impure part (which dirs to read) belongs to the caller; this
|
|
13
|
+
* is the deterministic merge that is unit-tested in isolation.
|
|
14
|
+
*/
|
|
15
|
+
import type { H2AEnvelope } from "@sentropic/h2a";
|
|
16
|
+
/**
|
|
17
|
+
* Merge envelope sets, deduplicated by `envelope.id`. Pass the CURRENT inbox
|
|
18
|
+
* first: on an id collision the earlier set wins (identical content is expected,
|
|
19
|
+
* but precedence is defined). Entries without a string `id` are skipped. The
|
|
20
|
+
* result is sorted by `id` ascending, matching the single-dir reader's
|
|
21
|
+
* filename `.sort()`, so a dual-read is indistinguishable from one merged dir.
|
|
22
|
+
*/
|
|
23
|
+
export declare function mergeInboxDedup(sets: ReadonlyArray<readonly H2AEnvelope[]>): H2AEnvelope[];
|
|
24
|
+
export interface LegacyAdoptionInput {
|
|
25
|
+
/** Has some agent already inherited this legacy id's keyring (single-inheritor lock)? */
|
|
26
|
+
readonly legacyAlreadyAdopted: boolean;
|
|
27
|
+
/** Did this connector prove possession of one of the legacy keyring's keys? */
|
|
28
|
+
readonly provedLegacyPossession: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface LegacyAdoptionDecision {
|
|
31
|
+
/** Adopt the legacy id as an alias of this agent's perennial uuid + inherit its keyring. */
|
|
32
|
+
readonly adopt: boolean;
|
|
33
|
+
/** Mint a fresh key for this agent (honest re-key for de-collided peers). */
|
|
34
|
+
readonly netNewKeys: boolean;
|
|
35
|
+
readonly reason: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Ratified migration rule (DEC-116, spec §Migration F4): the FIRST agent to
|
|
39
|
+
* prove possession of a legacy key inherits the legacy keyring and adopts the
|
|
40
|
+
* legacy id as an alias of its new perennial uuid; every de-collided peer mints
|
|
41
|
+
* **net-new keys** (honest re-key, surfaced in the migration notice). No proof
|
|
42
|
+
* → no inheritance. Pure + total. The adoption record + keyring copy are the
|
|
43
|
+
* caller's (impure, locked) job; this is the deterministic decision.
|
|
44
|
+
*/
|
|
45
|
+
export declare function decideLegacyAdoption(input: LegacyAdoptionInput): LegacyAdoptionDecision;
|
|
46
|
+
export interface H2AIdentityAlias {
|
|
47
|
+
readonly instance: string;
|
|
48
|
+
readonly legacyInstance: string;
|
|
49
|
+
readonly adoptedKeyring: boolean;
|
|
50
|
+
readonly at: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function listIdentityAliases(root: string, instance?: string): H2AIdentityAlias[];
|
|
53
|
+
export declare function legacyAliasAlreadyAdopted(root: string, legacyInstance: string): boolean;
|
|
54
|
+
export declare function recordIdentityAlias(root: string, alias: H2AIdentityAlias): void;
|
|
55
|
+
//# sourceMappingURL=migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,CAAC,SAAS,WAAW,EAAE,CAAC,GAC1C,WAAW,EAAE,CAUf;AAED,MAAM,WAAW,mBAAmB;IAClC,yFAAyF;IACzF,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,+EAA+E;IAC/E,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACrC,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,sBAAsB,CAoBvF;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAUD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAcvF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAIvF;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAQ/E"}
|