@econ-v1/ports 7.5.27 → 7.5.29

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.
@@ -41,7 +41,7 @@ export type KeyInspectionFailure = {
41
41
  readonly detectedAt: string;
42
42
  readonly generation: number;
43
43
  readonly keyId?: string;
44
- readonly reason: "key-id-mismatch" | "shape-invalid" | "signature-invalid" | "wrapped-key-unreadable";
44
+ readonly reason: "key-id-mismatch" | "key-material-missing" | "shape-invalid" | "signature-invalid" | "wrapped-key-unreadable";
45
45
  };
46
46
  export type IdentityPort = {
47
47
  generate: () => Promise<DeviceIdentity>;
@@ -62,5 +62,23 @@ export type IdentityPort = {
62
62
  recheckIdentity?: () => Promise<DeviceIdentity>;
63
63
  resetUnusableIdentity?: () => Promise<DeviceIdentity>;
64
64
  loadKeyInspectionFailure?: () => Promise<KeyInspectionFailure | undefined>;
65
+ /**
66
+ * Durable "has this browser ever been
67
+ * paired" signal (key-safety gaps Task 5, docs/superpowers/plans/2026-10-08-key-safety-gaps.md),
68
+ * read from DURABLE identity evidence — never from in-memory session state, which reads
69
+ * `"none"` on every runtime restart before re-establishment and says nothing about history.
70
+ * Never-paired is: no delegation ever stored, no connection-metadata ever stored, no
71
+ * key-inspection-failure diagnostic ever recorded, AND the lifecycle is either absent or still
72
+ * `"active"` at generation 1 (no lifecycle transition — revoke, quarantine, or key
73
+ * replacement — has ever happened). A lone pairing-attempt name (a device name typed before
74
+ * approval completes) does NOT count as history: no delegation was ever issued, so this
75
+ * browser still has nothing a legacy token's wider scope would improperly extend. A failing
76
+ * read MUST resolve `true` (fail closed) — treating an unreadable history as "never paired"
77
+ * would hand out the legacy owner token on exactly the browsers it is least safe to trust.
78
+ * Optional so a composition without it (or an underlying `IdentityPort` that predates it)
79
+ * degrades to "has history" wherever `createDeviceSessionAccessToken` checks it — never to
80
+ * "never paired" by omission.
81
+ */
82
+ hasPairingHistory?: () => Promise<boolean>;
65
83
  };
66
84
  //# sourceMappingURL=identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.js"],"names":[],"mappings":"mCAEc,OAAO,wBAAwB,EAAE,oBAAoB;8BAErD;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE;6BACvB,iBAAiB,GAAG,SAAS;mCAC7B;IAAE,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE;+BAC5H;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;uCACzJ;IAAE,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;6BACzK,oBAAoB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAA;CAAE;kCAC9D;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;gCACnG,QAAQ,GAAG,SAAS,GAAG,UAAU;;;;;;mCAKlC;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,mBAAmB,GAAG,wBAAwB,CAAA;CAAE;;cAK3L,MAAM,OAAO,CAAC,cAAc,CAAC;UAC7B,CAAC,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC;oBACxE,MAAM,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;sBAC/C,MAAM,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;oBAC/C,MAAM,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;qBAC3C,CAAC,UAAU,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC;4BAC/C,MAAM,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC;6BACnD,CAAC,QAAQ,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC;qBACrD,MAAM,OAAO,CAAC,IAAI,CAAC;WACnB,MAAM,OAAO,CAAC,IAAI,CAAC;4BACnB,MAAM,OAAO,CAAC,cAAc,CAAC;iBAC7B,MAAM,OAAO,CAAC,mBAAmB,CAAC;oBAClC,MAAM,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;6BAC5C,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;8BACjC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAC/B,MAAM,OAAO,CAAC,cAAc,CAAC;4BAC7B,MAAM,OAAO,CAAC,cAAc,CAAC;+BAC7B,MAAM,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.js"],"names":[],"mappings":"mCAEc,OAAO,wBAAwB,EAAE,oBAAoB;8BAErD;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE;6BACvB,iBAAiB,GAAG,SAAS;mCAC7B;IAAE,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE;+BAC5H;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;uCACzJ;IAAE,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;6BACzK,oBAAoB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAA;CAAE;kCAC9D;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;gCACnG,QAAQ,GAAG,SAAS,GAAG,UAAU;;;;;;mCAKlC;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,sBAAsB,GAAG,eAAe,GAAG,mBAAmB,GAAG,wBAAwB,CAAA;CAAE;;cAKpN,MAAM,OAAO,CAAC,cAAc,CAAC;UAC7B,CAAC,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC;oBACxE,MAAM,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;sBAC/C,MAAM,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;oBAC/C,MAAM,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;qBAC3C,CAAC,UAAU,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC;4BAC/C,MAAM,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC;6BACnD,CAAC,QAAQ,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC;qBACrD,MAAM,OAAO,CAAC,IAAI,CAAC;WACnB,MAAM,OAAO,CAAC,IAAI,CAAC;4BACnB,MAAM,OAAO,CAAC,cAAc,CAAC;iBAC7B,MAAM,OAAO,CAAC,mBAAmB,CAAC;oBAClC,MAAM,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;6BAC5C,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;8BACjC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAC/B,MAAM,OAAO,CAAC,cAAc,CAAC;4BAC7B,MAAM,OAAO,CAAC,cAAc,CAAC;+BAC7B,MAAM,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;wBAC/C,MAAM,OAAO,CAAC,OAAO,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@econ-v1/ports",
3
- "version": "7.5.27",
3
+ "version": "7.5.29",
4
4
  "description": "Platform-neutral ports for Node client applications",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "author": "Node contributors",
package/src/identity.js CHANGED
@@ -14,7 +14,7 @@
14
14
  * Durable, non-sensitive record of why stored key material was quarantined (lifecycle
15
15
  * `"unusable"`) rather than purged — never holds key bytes. See
16
16
  * docs/superpowers/plans/2026-10-08-no-silent-device-key-purge.md.
17
- * @typedef {{ readonly detectedAt: string, readonly generation: number, readonly keyId?: string, readonly reason: "key-id-mismatch" | "shape-invalid" | "signature-invalid" | "wrapped-key-unreadable" }} KeyInspectionFailure
17
+ * @typedef {{ readonly detectedAt: string, readonly generation: number, readonly keyId?: string, readonly reason: "key-id-mismatch" | "key-material-missing" | "shape-invalid" | "signature-invalid" | "wrapped-key-unreadable" }} KeyInspectionFailure
18
18
  */
19
19
 
20
20
  /**
@@ -37,6 +37,21 @@
37
37
  * @property {() => Promise<DeviceIdentity>} [recheckIdentity]
38
38
  * @property {() => Promise<DeviceIdentity>} [resetUnusableIdentity]
39
39
  * @property {() => Promise<KeyInspectionFailure | undefined>} [loadKeyInspectionFailure]
40
+ * @property {() => Promise<boolean>} [hasPairingHistory] Durable "has this browser ever been
41
+ * paired" signal (key-safety gaps Task 5, docs/superpowers/plans/2026-10-08-key-safety-gaps.md),
42
+ * read from DURABLE identity evidence — never from in-memory session state, which reads
43
+ * `"none"` on every runtime restart before re-establishment and says nothing about history.
44
+ * Never-paired is: no delegation ever stored, no connection-metadata ever stored, no
45
+ * key-inspection-failure diagnostic ever recorded, AND the lifecycle is either absent or still
46
+ * `"active"` at generation 1 (no lifecycle transition — revoke, quarantine, or key
47
+ * replacement — has ever happened). A lone pairing-attempt name (a device name typed before
48
+ * approval completes) does NOT count as history: no delegation was ever issued, so this
49
+ * browser still has nothing a legacy token's wider scope would improperly extend. A failing
50
+ * read MUST resolve `true` (fail closed) — treating an unreadable history as "never paired"
51
+ * would hand out the legacy owner token on exactly the browsers it is least safe to trust.
52
+ * Optional so a composition without it (or an underlying `IdentityPort` that predates it)
53
+ * degrades to "has history" wherever `createDeviceSessionAccessToken` checks it — never to
54
+ * "never paired" by omission.
40
55
  */
41
56
 
42
57
  export {};