@sentropic/h2a-cli 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/bin.js +4 -1
  2. package/dist/bin.js.map +1 -1
  3. package/dist/cli-contract.d.ts.map +1 -1
  4. package/dist/cli-contract.js +33 -1
  5. package/dist/cli-contract.js.map +1 -1
  6. package/dist/cli.d.ts +10 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +175 -20
  9. package/dist/cli.js.map +1 -1
  10. package/dist/hosts/agy.d.ts +14 -0
  11. package/dist/hosts/agy.d.ts.map +1 -0
  12. package/dist/hosts/agy.js +47 -0
  13. package/dist/hosts/agy.js.map +1 -0
  14. package/dist/hosts/plugin.d.ts +52 -0
  15. package/dist/hosts/plugin.d.ts.map +1 -0
  16. package/dist/hosts/plugin.js +74 -0
  17. package/dist/hosts/plugin.js.map +1 -0
  18. package/dist/index.d.ts +7 -4
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +6 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/mcp.d.ts +1 -1
  23. package/dist/mcp.d.ts.map +1 -1
  24. package/dist/mcp.js +1 -0
  25. package/dist/mcp.js.map +1 -1
  26. package/dist/runtime/escalation/index.d.ts +2 -0
  27. package/dist/runtime/escalation/index.d.ts.map +1 -0
  28. package/dist/runtime/escalation/index.js +2 -0
  29. package/dist/runtime/escalation/index.js.map +1 -0
  30. package/dist/runtime/escalation/registry.d.ts +40 -0
  31. package/dist/runtime/escalation/registry.d.ts.map +1 -0
  32. package/dist/runtime/escalation/registry.js +79 -0
  33. package/dist/runtime/escalation/registry.js.map +1 -0
  34. package/dist/runtime/local-files/paths.d.ts +1 -0
  35. package/dist/runtime/local-files/paths.d.ts.map +1 -1
  36. package/dist/runtime/local-files/paths.js +2 -1
  37. package/dist/runtime/local-files/paths.js.map +1 -1
  38. package/dist/runtime/mcp/handlers.d.ts +4 -0
  39. package/dist/runtime/mcp/handlers.d.ts.map +1 -1
  40. package/dist/runtime/mcp/handlers.js +21 -1
  41. package/dist/runtime/mcp/handlers.js.map +1 -1
  42. package/dist/runtime/mcp/server.d.ts.map +1 -1
  43. package/dist/runtime/mcp/server.js +3 -1
  44. package/dist/runtime/mcp/server.js.map +1 -1
  45. package/dist/runtime/mcp/tools.d.ts.map +1 -1
  46. package/dist/runtime/mcp/tools.js +12 -0
  47. package/dist/runtime/mcp/tools.js.map +1 -1
  48. package/dist/runtime/sysml/client.d.ts +44 -0
  49. package/dist/runtime/sysml/client.d.ts.map +1 -0
  50. package/dist/runtime/sysml/client.js +52 -0
  51. package/dist/runtime/sysml/client.js.map +1 -0
  52. package/dist/runtime/sysml/disclosure.d.ts +23 -0
  53. package/dist/runtime/sysml/disclosure.d.ts.map +1 -0
  54. package/dist/runtime/sysml/disclosure.js +53 -0
  55. package/dist/runtime/sysml/disclosure.js.map +1 -0
  56. package/dist/runtime/sysml/index.d.ts +4 -0
  57. package/dist/runtime/sysml/index.d.ts.map +1 -0
  58. package/dist/runtime/sysml/index.js +4 -0
  59. package/dist/runtime/sysml/index.js.map +1 -0
  60. package/dist/runtime/sysml/verify.d.ts +32 -0
  61. package/dist/runtime/sysml/verify.d.ts.map +1 -0
  62. package/dist/runtime/sysml/verify.js +67 -0
  63. package/dist/runtime/sysml/verify.js.map +1 -0
  64. package/package.json +2 -2
  65. package/skills/h2a/SKILL.md +10 -2
@@ -0,0 +1,52 @@
1
+ /**
2
+ * DEC-098 — SysML v2 interop S2 (spec: docs/sysml-interop.md §7, DEC-081). The
3
+ * I/O adapter: fetch a referenced element from the SysML v2 API & Services and
4
+ * canonical-hash it for content-integrity (trust level (b), §4). Pure ref types
5
+ * stay in core (S1); all I/O lives here. The verify path + CLI are S3.
6
+ *
7
+ * Endpoint follows the OMG SysML v2 API & Services REST/HTTP PSM:
8
+ * GET {apiBase}/projects/{project}/commits/{commit}/elements/{element}
9
+ *
10
+ * The HTTP client is injectable (`fetchImpl`) so the adapter is unit-testable
11
+ * against a mock API with no network. API credentials are held out-of-band and
12
+ * passed per call (`auth`); h2a never embeds them in envelopes (§6).
13
+ */
14
+ import { computeHash } from "@sentropic/h2a";
15
+ function resolveBase(ref, options) {
16
+ const base = options.apiBase ?? ref.apiBase;
17
+ if (!base) {
18
+ throw new Error("resolveSysmlElement: apiBase is required (pass it or set ref.apiBase)");
19
+ }
20
+ return base.replace(/\/+$/, "");
21
+ }
22
+ /**
23
+ * Fetch the referenced element at its immutable commit. Requires `ref.element`
24
+ * (whole-project resolution — `element` omitted — is a later slice; default
25
+ * documented in docs/loop-decisions.md). Throws on a non-OK HTTP status.
26
+ */
27
+ export async function resolveSysmlElement(ref, options = {}) {
28
+ if (!ref.element) {
29
+ throw new Error("resolveSysmlElement: ref.element is required (whole-project resolution is not supported yet)");
30
+ }
31
+ const base = resolveBase(ref, options);
32
+ const url = `${base}/projects/${encodeURIComponent(ref.project)}/commits/${encodeURIComponent(ref.commit)}/elements/${encodeURIComponent(ref.element)}`;
33
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
34
+ if (!fetchImpl) {
35
+ throw new Error("resolveSysmlElement: no fetch implementation available (pass fetchImpl)");
36
+ }
37
+ const headers = options.auth ? { Authorization: `Bearer ${options.auth}` } : undefined;
38
+ const res = await fetchImpl(url, headers ? { headers } : undefined);
39
+ if (!res.ok) {
40
+ throw new Error(`resolveSysmlElement: ${url} returned HTTP ${res.status}`);
41
+ }
42
+ return res.json();
43
+ }
44
+ /**
45
+ * Canonical hash of a fetched element, for content-integrity (trust level (b)).
46
+ * Reuses the core canonical hashing (DEC-035) so the value is comparable to a
47
+ * `ref.elementHash` embedded at sign time.
48
+ */
49
+ export function hashSysmlElement(element) {
50
+ return computeHash(element);
51
+ }
52
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/runtime/sysml/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAoB,MAAM,gBAAgB,CAAC;AAuB/D,SAAS,WAAW,CAAC,GAAgB,EAAE,OAA4B;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAgB,EAChB,UAA+B,EAAE;IAEjC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,8FAA8F,CAC/F,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,GAAG,IAAI,aAAa,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,kBAAkB,CAC3F,GAAG,CAAC,MAAM,CACX,aAAa,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;IAChD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAK,UAAU,CAAC,KAA+C,CAAC;IACnG,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACvF,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * DEC-100 — SysML v2 interop S4 (spec §5, DEC-081). Map an h2a disclosure mode
3
+ * (DEC-045) onto a SysML v2 **query scope**: what a CONTROL / recipient may read
4
+ * through the API, expressed abstractly (the concrete API params / SysML `view`
5
+ * id are repo-specific — this is the policy→scope decision, not the wire call).
6
+ *
7
+ * Pure + total over the six disclosure modes.
8
+ */
9
+ import type { H2ADisclosureMode } from "@sentropic/h2a";
10
+ /** How much of the referenced element the recipient may read. */
11
+ export type H2ASysmlQueryDetail = "none" | "attestation" | "metadata" | "redacted" | "full";
12
+ export interface H2ASysmlQueryScope {
13
+ readonly mode: H2ADisclosureMode;
14
+ /** Whether the adapter should fetch element content at all. */
15
+ readonly fetch: boolean;
16
+ readonly detail: H2ASysmlQueryDetail;
17
+ /** Suggested SysML view id (viewpoint/view mechanism) when a filtered query applies. */
18
+ readonly view?: string;
19
+ readonly note: string;
20
+ }
21
+ /** Total: every disclosure mode maps to a query scope. */
22
+ export declare function sysmlQueryScope(mode: H2ADisclosureMode): H2ASysmlQueryScope;
23
+ //# sourceMappingURL=disclosure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["../../../src/runtime/sysml/disclosure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,iEAAiE;AACjE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAE5F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,wFAAwF;IACxF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AA2CD,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,CAE3E"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * DEC-100 — SysML v2 interop S4 (spec §5, DEC-081). Map an h2a disclosure mode
3
+ * (DEC-045) onto a SysML v2 **query scope**: what a CONTROL / recipient may read
4
+ * through the API, expressed abstractly (the concrete API params / SysML `view`
5
+ * id are repo-specific — this is the policy→scope decision, not the wire call).
6
+ *
7
+ * Pure + total over the six disclosure modes.
8
+ */
9
+ const SCOPES = {
10
+ denied: {
11
+ mode: "denied",
12
+ fetch: false,
13
+ detail: "none",
14
+ note: "no access — the recipient may not query the model"
15
+ },
16
+ "hash-only": {
17
+ mode: "hash-only",
18
+ fetch: false,
19
+ detail: "none",
20
+ note: "compare the embedded elementHash only; no content query"
21
+ },
22
+ attestation: {
23
+ mode: "attestation",
24
+ fetch: false,
25
+ detail: "attestation",
26
+ note: "the signed envelope (with elementHash) is the attestation; no content query"
27
+ },
28
+ "evidence-package": {
29
+ mode: "evidence-package",
30
+ fetch: true,
31
+ detail: "metadata",
32
+ note: "fetch element metadata + hash for an evidence package (not full content)"
33
+ },
34
+ "redacted-view": {
35
+ mode: "redacted-view",
36
+ fetch: true,
37
+ detail: "redacted",
38
+ view: "redacted",
39
+ note: "query a SysML redacted view (sensitive members excluded)"
40
+ },
41
+ "full-view": {
42
+ mode: "full-view",
43
+ fetch: true,
44
+ detail: "full",
45
+ view: "full",
46
+ note: "query the full element"
47
+ }
48
+ };
49
+ /** Total: every disclosure mode maps to a query scope. */
50
+ export function sysmlQueryScope(mode) {
51
+ return SCOPES[mode];
52
+ }
53
+ //# sourceMappingURL=disclosure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure.js","sourceRoot":"","sources":["../../../src/runtime/sysml/disclosure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH,MAAM,MAAM,GAAkD;IAC5D,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,mDAAmD;KAC1D;IACD,WAAW,EAAE;QACX,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,yDAAyD;KAChE;IACD,WAAW,EAAE;QACX,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,aAAa;QACrB,IAAI,EAAE,6EAA6E;KACpF;IACD,kBAAkB,EAAE;QAClB,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,UAAU;QAClB,IAAI,EAAE,0EAA0E;KACjF;IACD,eAAe,EAAE;QACf,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,UAAU;QAClB,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,0DAA0D;KACjE;IACD,WAAW,EAAE;QACX,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,wBAAwB;KAC/B;CACF,CAAC;AAEF,0DAA0D;AAC1D,MAAM,UAAU,eAAe,CAAC,IAAuB;IACrD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { resolveSysmlElement, hashSysmlElement, type SysmlFetchImpl, type SysmlFetchResponse, type ResolveSysmlOptions } from "./client.js";
2
+ export { verifyEnvelopeSysmlRef, extractSysmlRef, type VerifyEnvelopeSysmlOptions, type VerifyEnvelopeSysmlResult } from "./verify.js";
3
+ export { sysmlQueryScope, type H2ASysmlQueryScope, type H2ASysmlQueryDetail } from "./disclosure.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/sysml/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { resolveSysmlElement, hashSysmlElement } from "./client.js";
2
+ export { verifyEnvelopeSysmlRef, extractSysmlRef } from "./verify.js";
3
+ export { sysmlQueryScope } from "./disclosure.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/sysml/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAIjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,eAAe,EAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EAGhB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * DEC-099 — SysML v2 interop S3 (spec §4, DEC-081). Verify that an envelope's
3
+ * embedded `H2ASysmlRef` is (a) signed by the claimed actor — **commit-trust**,
4
+ * the default: a valid signature over an immutable commit is enough — and
5
+ * optionally (b) **content-integrity**: re-fetch the element (S2) and check its
6
+ * canonical hash against the `elementHash` embedded at sign time, catching a
7
+ * repository that violated immutability or a wrong `apiBase`.
8
+ */
9
+ import { type H2AEnvelope, type H2ASysmlRef } from "@sentropic/h2a";
10
+ import { type SysmlFetchImpl } from "./client.js";
11
+ /** Extract the ref from the conventional location `body.subject.sysmlRef` (spec §2). */
12
+ export declare function extractSysmlRef(envelope: H2AEnvelope): H2ASysmlRef | undefined;
13
+ export interface VerifyEnvelopeSysmlOptions {
14
+ /** Public key to verify the envelope signature against (commit-trust). */
15
+ readonly publicKeyPem: string;
16
+ /** Only accept a signature from this signer id. */
17
+ readonly by?: string;
18
+ /** Also re-fetch + re-hash the element and compare to `ref.elementHash`. */
19
+ readonly contentIntegrity?: boolean;
20
+ readonly apiBase?: string;
21
+ readonly auth?: string;
22
+ readonly fetchImpl?: SysmlFetchImpl;
23
+ }
24
+ export interface VerifyEnvelopeSysmlResult {
25
+ readonly ok: boolean;
26
+ readonly ref?: H2ASysmlRef;
27
+ readonly signatureVerified: boolean;
28
+ readonly contentVerified?: boolean;
29
+ readonly reason?: string;
30
+ }
31
+ export declare function verifyEnvelopeSysmlRef(envelope: H2AEnvelope, options: VerifyEnvelopeSysmlOptions): Promise<VerifyEnvelopeSysmlResult>;
32
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/runtime/sysml/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAyC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzF,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAO9E;AAED,MAAM,WAAW,0BAA0B;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,yBAAyB,CAAC,CA8CpC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * DEC-099 — SysML v2 interop S3 (spec §4, DEC-081). Verify that an envelope's
3
+ * embedded `H2ASysmlRef` is (a) signed by the claimed actor — **commit-trust**,
4
+ * the default: a valid signature over an immutable commit is enough — and
5
+ * optionally (b) **content-integrity**: re-fetch the element (S2) and check its
6
+ * canonical hash against the `elementHash` embedded at sign time, catching a
7
+ * repository that violated immutability or a wrong `apiBase`.
8
+ */
9
+ import { isH2ASysmlRef, validateSysmlRef, verifyEnvelopeSignature } from "@sentropic/h2a";
10
+ import { hashSysmlElement, resolveSysmlElement } from "./client.js";
11
+ /** Extract the ref from the conventional location `body.subject.sysmlRef` (spec §2). */
12
+ export function extractSysmlRef(envelope) {
13
+ const body = envelope.body;
14
+ if (!body || typeof body !== "object")
15
+ return undefined;
16
+ const subject = body.subject;
17
+ if (!subject || typeof subject !== "object")
18
+ return undefined;
19
+ const ref = subject.sysmlRef;
20
+ return isH2ASysmlRef(ref) ? ref : undefined;
21
+ }
22
+ export async function verifyEnvelopeSysmlRef(envelope, options) {
23
+ const ref = extractSysmlRef(envelope);
24
+ if (!ref)
25
+ return { ok: false, signatureVerified: false, reason: "no-sysml-ref" };
26
+ const validation = validateSysmlRef(ref);
27
+ if (!validation.ok) {
28
+ return { ok: false, ref, signatureVerified: false, reason: `invalid-ref:${validation.errors.join(",")}` };
29
+ }
30
+ const signatureVerified = verifyEnvelopeSignature(envelope, options.publicKeyPem, options.by ? { by: options.by } : {});
31
+ if (!signatureVerified) {
32
+ return { ok: false, ref, signatureVerified: false, reason: "signature-failed" };
33
+ }
34
+ // (a) commit-trust: a valid signature over the immutable commit is enough.
35
+ if (!options.contentIntegrity) {
36
+ return { ok: true, ref, signatureVerified: true };
37
+ }
38
+ // (b) content-integrity: re-fetch + re-hash + compare.
39
+ if (!ref.elementHash) {
40
+ return { ok: false, ref, signatureVerified: true, contentVerified: false, reason: "no-element-hash" };
41
+ }
42
+ try {
43
+ const element = await resolveSysmlElement(ref, {
44
+ ...(options.apiBase ? { apiBase: options.apiBase } : {}),
45
+ ...(options.auth ? { auth: options.auth } : {}),
46
+ ...(options.fetchImpl ? { fetchImpl: options.fetchImpl } : {})
47
+ });
48
+ const contentVerified = hashSysmlElement(element) === ref.elementHash;
49
+ return {
50
+ ok: contentVerified,
51
+ ref,
52
+ signatureVerified: true,
53
+ contentVerified,
54
+ ...(contentVerified ? {} : { reason: "content-hash-mismatch" })
55
+ };
56
+ }
57
+ catch (err) {
58
+ return {
59
+ ok: false,
60
+ ref,
61
+ signatureVerified: true,
62
+ contentVerified: false,
63
+ reason: `fetch-failed:${err.message}`
64
+ };
65
+ }
66
+ }
67
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/runtime/sysml/verify.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.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Unified CLI surface for h2a hosts and MCP-oriented coordination flows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -40,7 +40,7 @@
40
40
  "skills"
41
41
  ],
42
42
  "dependencies": {
43
- "@sentropic/h2a": "^0.11.0"
43
+ "@sentropic/h2a": "^0.13.0"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public"
@@ -35,7 +35,7 @@ Steps:
35
35
  1. Verify the `h2a` binary is on PATH (`h2a --help`). If absent, instruct the user to run `npm i -g @sentropic/h2a-cli@latest` and stop.
36
36
  2. Decide the shared root. If `[root]` was passed, use it; otherwise prefer `<this-workspace>/.h2a`, else `~/h2a-workspace/.h2a`. Confirm with the user only if ambiguous.
37
37
  3. Run `h2a init --root <root>` (idempotent).
38
- 4. Pick an instance id. Default: `<host>:<workspace-leaf>` (host = claude|codex|gemini; workspace-leaf = `basename <cwd>`).
38
+ 4. Pick an instance id. Default: `<host>:<workspace-leaf>` (host = claude|codex|gemini|agy; workspace-leaf = `basename <cwd>`).
39
39
  5. Call the MCP tool `h2a_session_open` with `{ instance, host, interests: { scopes: ["scope:default"], negotiations: [] } }`.
40
40
  6. Print a short summary: instance id, session id, peers currently live, the four notification topics this session is subscribed to.
41
41
 
@@ -180,4 +180,12 @@ These can be invoked directly from the shell at any time, outside the slash-comm
180
180
  - `h2a doctor [--root <path>]` — quick health probe.
181
181
  - `h2a sessions [--root <path>]` — same listing as `/h2a discover` but from the shell.
182
182
  - `h2a keys generate --instance <id>` — produce an ed25519 PEM keypair.
183
- - `h2a install-skills --host <claude|codex|gemini>` — re-install or update this skill on another host.
183
+ - `h2a install-skills --host <claude|codex|gemini|agy>` — re-install or update this skill on another host. *(For **agy**/Antigravity the skill is written to the shared `~/.gemini/commands/h2a.toml`; the command then prints an `importHint` — run `agy plugin import gemini` (then `agy plugin enable h2a`) to pull it into agy. DEC-096/101.)*
184
+
185
+ **Operational surfaces** (also shell-invocable; matching `h2a_*` MCP tools where noted):
186
+
187
+ - `h2a nhi report|inventory|attest|offboard|export` — Non-Human-Identity posture / inventory / signed attestation / coordinated offboard / SPIFFE-bundle export (`h2a_nhi_*`, DEC-087..090/094).
188
+ - `h2a blockage raise|list|resolve` — the peer blockage feedback loop, distinct from the drumbeat and from escalation (`h2a_blockage_*`, DEC-092). Subscribed sessions get `peer.blocked`/`peer.unblocked` pushes.
189
+ - `h2a drumbeat record|scan|clear|escalations|watch` — anti-stall relance daemon + escalation-to-PRINCIPAL (DEC-086/091/095).
190
+ - `h2a sysml verify --json <env> --public-key <pem>` — verify a SysML-v2 ref embedded in a signed envelope (commit-trust + content-integrity, DEC-099).
191
+ - `h2a host setup|status|plugin --host <codex|claude|gemini|agy>` — render the per-host MCP config / stop-hook glue (DEC-093/096).