@geohar/un-bien 0.7.0 → 0.9.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 (89) hide show
  1. package/README.md +237 -268
  2. package/dist/bin/launcher.js +38 -0
  3. package/dist/bin/launcher.js.map +1 -0
  4. package/dist/config.d.ts +41 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/daemon/install.d.ts +33 -35
  7. package/dist/daemon/install.js +43 -73
  8. package/dist/daemon/install.js.map +1 -1
  9. package/dist/enrich_tool_args.d.ts +9 -0
  10. package/dist/enrich_tool_args.js +171 -0
  11. package/dist/enrich_tool_args.js.map +1 -0
  12. package/dist/image_codec.d.ts +22 -0
  13. package/dist/image_codec.js +149 -0
  14. package/dist/image_codec.js.map +1 -0
  15. package/dist/index.d.ts +0 -26
  16. package/dist/index.js +235 -1237
  17. package/dist/index.js.map +1 -1
  18. package/dist/launch.d.ts +34 -0
  19. package/dist/launch.js +171 -0
  20. package/dist/launch.js.map +1 -0
  21. package/dist/launcher/launcher.d.ts +6 -0
  22. package/dist/launcher/launcher.js +188 -0
  23. package/dist/launcher/launcher.js.map +1 -0
  24. package/dist/pairing/crypto.d.ts +4 -0
  25. package/dist/pairing/crypto.js +10 -0
  26. package/dist/pairing/crypto.js.map +1 -1
  27. package/dist/pairing/peer_trust.d.ts +20 -0
  28. package/dist/pairing/peer_trust.js +82 -0
  29. package/dist/pairing/peer_trust.js.map +1 -0
  30. package/dist/pairing/storage.d.ts +51 -26
  31. package/dist/pairing/storage.js +346 -136
  32. package/dist/pairing/storage.js.map +1 -1
  33. package/dist/panel_bridge.d.ts +3 -1
  34. package/dist/panel_bridge.js +10 -10
  35. package/dist/panel_bridge.js.map +1 -1
  36. package/dist/rooms.d.ts +16 -0
  37. package/dist/rooms.js +22 -0
  38. package/dist/rooms.js.map +1 -1
  39. package/dist/session/debug_log.js +2 -2
  40. package/dist/session/debug_log.js.map +1 -1
  41. package/dist/session/local_config.js +2 -0
  42. package/dist/session/local_config.js.map +1 -1
  43. package/dist/session/rpc_envelope.d.ts +18 -0
  44. package/dist/session/rpc_envelope.js +1 -1
  45. package/dist/session/rpc_envelope.js.map +1 -1
  46. package/dist/session/rpc_inbound.d.ts +2 -2
  47. package/dist/session/rpc_inbound.js +1 -1
  48. package/dist/session/rpc_inbound.js.map +1 -1
  49. package/dist/subagent_rooms.d.ts +49 -0
  50. package/dist/subagent_rooms.js +787 -0
  51. package/dist/subagent_rooms.js.map +1 -0
  52. package/dist/transport/peer_channel.d.ts +7 -1
  53. package/dist/transport/peer_channel.js +8 -1
  54. package/dist/transport/peer_channel.js.map +1 -1
  55. package/dist/transport/relay_client.d.ts +19 -0
  56. package/dist/transport/relay_client.js.map +1 -1
  57. package/docs/daemon.md +65 -64
  58. package/package.json +13 -11
  59. package/service-templates/launchd.plist.template +5 -5
  60. package/service-templates/systemd.service.template +2 -2
  61. package/service-templates/task-launcher.vbs.template +5 -5
  62. package/service-templates/task-scheduler.xml.template +1 -1
  63. package/dist/bin/supervisord.js +0 -86
  64. package/dist/bin/supervisord.js.map +0 -1
  65. package/dist/daemon/client.d.ts +0 -20
  66. package/dist/daemon/client.js +0 -131
  67. package/dist/daemon/client.js.map +0 -1
  68. package/dist/daemon/control_protocol.d.ts +0 -176
  69. package/dist/daemon/control_protocol.js +0 -63
  70. package/dist/daemon/control_protocol.js.map +0 -1
  71. package/dist/daemon/cron_log.d.ts +0 -45
  72. package/dist/daemon/cron_log.js +0 -71
  73. package/dist/daemon/cron_log.js.map +0 -1
  74. package/dist/daemon/cron_registry.d.ts +0 -80
  75. package/dist/daemon/cron_registry.js +0 -198
  76. package/dist/daemon/cron_registry.js.map +0 -1
  77. package/dist/daemon/id.d.ts +0 -24
  78. package/dist/daemon/id.js +0 -36
  79. package/dist/daemon/id.js.map +0 -1
  80. package/dist/daemon/registry.d.ts +0 -63
  81. package/dist/daemon/registry.js +0 -153
  82. package/dist/daemon/registry.js.map +0 -1
  83. package/dist/daemon/rpc_child.d.ts +0 -194
  84. package/dist/daemon/rpc_child.js +0 -419
  85. package/dist/daemon/rpc_child.js.map +0 -1
  86. package/dist/daemon/supervisor.d.ts +0 -93
  87. package/dist/daemon/supervisor.js +0 -666
  88. package/dist/daemon/supervisor.js.map +0 -1
  89. /package/dist/bin/{supervisord.d.ts → launcher.d.ts} +0 -0
@@ -13,6 +13,13 @@ export declare class KeyringUnavailableError extends Error {
13
13
  export declare class PairedIdentityMissingError extends Error {
14
14
  constructor(pairedCount: number, cause: unknown);
15
15
  }
16
+ /** Raised when the file-backend identity EXISTS but cannot be read or parsed
17
+ * (bad permissions, corruption). Treating that as "no identity" would let the
18
+ * resolver mint a fresh seed over a real one — the file-side version of the
19
+ * flop — so we FAIL LOUD instead of minting. */
20
+ export declare class FileIdentityUnreadableError extends Error {
21
+ constructor(path: string, cause: unknown);
22
+ }
16
23
  /**
17
24
  * Minimal backend interface for credential reads/writes. Swappable so
18
25
  * tests can inject a controlled in-memory store without touching the OS
@@ -40,36 +47,54 @@ export declare function _setKeyringExpectedForTest(value: boolean | null): void;
40
47
  /** Test-only: shrink retry attempts/delay so the persistent-failure path is
41
48
  * fast. `null`/omitted restores defaults. */
42
49
  export declare function _setKeyringRetryForTest(attempts: number | null, delayMs?: number): void;
50
+ export type IdentityStorageBackend = "keychain" | "file";
43
51
  /**
44
- * Returns the Pi-secret Ed25519 keypair, generating + persisting one on
45
- * first call. Resolution order:
46
- * 1. Existing file `~/.pi/un-bien/identity.json`, if presentit WINS over
47
- * the keyring. A file identity is only ever written by the headless/
48
- * degraded fallback (step 4) or an explicit `UNBIEN_ALLOW_FILE_IDENTITY`
49
- * opt-in, so its mere presence means this machine established its identity
50
- * as a file and the mobile device paired against THAT pubkey. If the
51
- * platform keyring later becomes readable (D-Bus/libsecret installed, a
52
- * desktop session, or a stale/other entry from another install), reading
53
- * it first would mask the file identity — returning a DIFFERENT key, or
54
- * (when the keyring is empty) minting a fresh one and persisting it —
55
- * silently breaking the existing pairing. So when both exist, file wins.
56
- * 2. New keyring service `dev.unbien.pi` (read retried — a transiently
57
- * locked Keychain throws; we don't treat that as "no key")
58
- * 3. Old keyring service `dev.unbien.mac` (migrate step 2, delete old)
59
- * 4. Generate a fresh keypair, BUT only when it's safe to: either both
60
- * keyring reads succeeded and returned nothing (genuine first run), or
61
- * the keyring is genuinely unavailable on a platform without a core one
62
- * (headless Linux → a file identity is minted here). On macOS/Windows a
63
- * persistent read failure with no file identity throws
64
- * `KeyringUnavailableError` instead of minting a new key — generating
65
- * there silently breaks existing pairing (the "lost pairing after idle"
66
- * bug). `UNBIEN_ALLOW_FILE_IDENTITY=1` opts back into a file identity
67
- * for headless macOS/Windows hosts.
52
+ * Returns this Pi's long-term Ed25519 identity, minting one only on a genuine
53
+ * first run. The seed is portable and its public key (epk) is what the relay
54
+ * routes on and what devices pair against so this resolver's ONE job is to
55
+ * never change the identity out from under an existing pairing (the "flop").
56
+ *
57
+ * Resolution (operator-selectable backend see design):
58
+ * 0. `UNBIEN_IDENTITY_SEED` env override always wins, read-only.
59
+ * 1. The SELECTED backend (`identity.storage`, default keychain): keychain
60
+ * (retried a locked Keychain throws, which is NOT "empty") or the 0600
61
+ * file at `identity.path`.
62
+ * 2. Migration READ-IN-PLACE of the OTHER backend recovers an existing
63
+ * identity (a keychain key when file is selected, or a file when keychain
64
+ * is selected) WITHOUT writing it through.
65
+ * 3. Generate + persist to the selected backend, but ONLY when every
66
+ * consulted source was genuinely empty. A keychain that THREW on a
67
+ * core-OS-keyring platform (macOS/Windows) is possibly-present
68
+ * `KeyringUnavailableError`, never minted over. Existing pairings
69
+ * `PairedIdentityMissingError`. A present-but-unreadable file
70
+ * `FileIdentityUnreadableError`. This is write-only-if-nonexistent: the
71
+ * resolver's only mutation is a genuine-first-run mint.
68
72
  *
69
- * Idempotent: subsequent calls return the same identity. The migration
70
- * runs at most once per machine (the old entry is deleted after copy).
73
+ * Idempotent. On headless Linux / a Bun-built pi (no usable keyring) the file
74
+ * backend is used automatically.
71
75
  */
72
76
  export declare function getOrCreateEd25519Keypair(): Promise<Ed25519Keypair>;
77
+ export interface IdentityInfo {
78
+ /** Base64 Ed25519 public key (epk) — PUBLIC, safe to display. `null` when no
79
+ * identity exists yet (one is minted on first real use). */
80
+ readonly epk: string | null;
81
+ /** The selected/effective storage backend. */
82
+ readonly backend: IdentityStorageBackend;
83
+ /** Where the identity resolved from (or would come from). */
84
+ readonly source: "env-override" | "keychain" | "file" | "none" | "error";
85
+ /** Resolved file-backend path. */
86
+ readonly filePath: string;
87
+ /** Human note (migration recovery, error cause, first-run hint). */
88
+ readonly detail?: string;
89
+ }
90
+ /**
91
+ * Reports the CURRENT identity state WITHOUT minting or mutating anything — the
92
+ * read-only backing for `unbien identity show`. Returns only NON-SECRET fields
93
+ * (epk is public); the private seed is NEVER included, since command output is
94
+ * LLM-visible. Read errors are surfaced as `source:"error"` with a `detail`,
95
+ * not thrown — this is a diagnostic.
96
+ */
97
+ export declare function describeIdentity(): Promise<IdentityInfo>;
73
98
  export interface PeerRecord {
74
99
  name: string;
75
100
  remote_epk: string;