@cello-protocol/daemon 0.0.79 → 0.0.81

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.
@@ -18,15 +18,21 @@
18
18
  * column present and the rows un-backfilled, which would skip the one-time step FOREVER;
19
19
  * - a RETHROW, because a migration that fails silently is a schema nobody can trust.
20
20
  *
21
- * DIRECTION OF THE BACKFILL. Existing rows become `accepted`, and that is correct rather than
22
- * lenient: every row that predates this column is portal-issued, minted about the operator, for the
23
- * operator, at their own action — there was never a third party whose decision was pending. Making
24
- * them `pending` would silently render every phone/email signal already in every wallet
25
- * unpresentable, which is a data-loss-shaped bug that raises no error.
21
+ * DIRECTION OF THE BACKFILL — ENFORCED BY THE SQL, NOT BY AN ARGUMENT ABOUT THE PAST.
22
+ * Portal-issued rows become `accepted`: they were minted about the operator, for the operator, at
23
+ * their own action, so there was never a third party whose decision was pending, and making them
24
+ * `pending` would silently render every phone/email signal already in every wallet unpresentable —
25
+ * a data-loss-shaped bug that raises no error. Agent-issued rows become `pending`, because somebody
26
+ * else authored them.
26
27
  *
27
- * NEW rows are a different question and are handled at the write path: an `issuer_kind: agent`
28
- * signal is inserted `pending`, because it is exactly the case where somebody else authored an
29
- * object about you.
28
+ * An earlier version backfilled everything to `accepted` on the reasoning that nothing agent-issued
29
+ * could exist yet. That was true only by RELEASE TIMING — the daemon has accepted
30
+ * `issuer_kind: agent` since M10 — so a dev or staging wallet that picked one up during M10B
31
+ * integration testing would have had it backfilled to presentable at boot, which is exactly the
32
+ * D-23 violation this file exists to prevent. Two WHERE clauses make it a property of the code.
33
+ *
34
+ * NEW rows are handled at the write path on the same axis: `putWalletSignal` inserts `pending` for
35
+ * `issuer_kind: agent` and `accepted` otherwise.
30
36
  */
31
37
  import type { DaemonDatabase } from "./sqlcipher-db.js";
32
38
  import type { Logger } from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"consent-migration.d.ts","sourceRoot":"","sources":["../src/consent-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAE9D,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAE3C,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA+BrF"}
1
+ {"version":3,"file":"consent-migration.d.ts","sourceRoot":"","sources":["../src/consent-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAE9D,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAE3C,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAqFrF"}
@@ -18,15 +18,21 @@
18
18
  * column present and the rows un-backfilled, which would skip the one-time step FOREVER;
19
19
  * - a RETHROW, because a migration that fails silently is a schema nobody can trust.
20
20
  *
21
- * DIRECTION OF THE BACKFILL. Existing rows become `accepted`, and that is correct rather than
22
- * lenient: every row that predates this column is portal-issued, minted about the operator, for the
23
- * operator, at their own action — there was never a third party whose decision was pending. Making
24
- * them `pending` would silently render every phone/email signal already in every wallet
25
- * unpresentable, which is a data-loss-shaped bug that raises no error.
21
+ * DIRECTION OF THE BACKFILL — ENFORCED BY THE SQL, NOT BY AN ARGUMENT ABOUT THE PAST.
22
+ * Portal-issued rows become `accepted`: they were minted about the operator, for the operator, at
23
+ * their own action, so there was never a third party whose decision was pending, and making them
24
+ * `pending` would silently render every phone/email signal already in every wallet unpresentable —
25
+ * a data-loss-shaped bug that raises no error. Agent-issued rows become `pending`, because somebody
26
+ * else authored them.
26
27
  *
27
- * NEW rows are a different question and are handled at the write path: an `issuer_kind: agent`
28
- * signal is inserted `pending`, because it is exactly the case where somebody else authored an
29
- * object about you.
28
+ * An earlier version backfilled everything to `accepted` on the reasoning that nothing agent-issued
29
+ * could exist yet. That was true only by RELEASE TIMING — the daemon has accepted
30
+ * `issuer_kind: agent` since M10 — so a dev or staging wallet that picked one up during M10B
31
+ * integration testing would have had it backfilled to presentable at boot, which is exactly the
32
+ * D-23 violation this file exists to prevent. Two WHERE clauses make it a property of the code.
33
+ *
34
+ * NEW rows are handled at the write path on the same axis: `putWalletSignal` inserts `pending` for
35
+ * `issuer_kind: agent` and `accepted` otherwise.
30
36
  */
31
37
  /** Present-tense truth for the reader: this is what gates presentation. */
32
38
  export const CONSENT_ACCEPTED = "accepted";
@@ -34,24 +40,82 @@ export function migrateWalletAddConsentState(db, logger) {
34
40
  const columns = new Set(db.prepare("PRAGMA table_info(wallet_trust_signals)").all().map((c) => c.name));
35
41
  // BIRTH GATE. Idempotent, and deliberately NOT "backfill wherever the value is NULL": a NULL that
36
42
  // appears later is not a legacy row, and promoting it would be the clobber this file prevents.
37
- if (columns.has("consent_state"))
43
+ //
44
+ // IT GATES ON BOTH COLUMNS, and gating on only `consent_state` was a real bug that shipped: every
45
+ // database that ran the previous release already had `consent_state`, so this returned here and
46
+ // `consent_notified_at` was NEVER ADDED on upgrade. Fresh installs got it, upgrades did not —
47
+ // exactly the fresh-vs-migrated divergence the suite has a test for, on a column that test did not
48
+ // cover. It stayed green because the partial-migration test asserted only NEGATIVES, which are
49
+ // satisfied by returning before any of the code under test runs.
50
+ if (columns.has("consent_state") && columns.has("consent_notified_at"))
38
51
  return;
39
- db.exec("BEGIN");
52
+ // BEGIN IMMEDIATE, not DEFERRED: a deferred transaction takes no write lock, so two daemons on one
53
+ // DB — a named real condition in this project — can both pass the gate above and the loser dies at
54
+ // boot on `duplicate column name`. It does not clobber, but it is a baffling crash. The lock also
55
+ // makes the re-read below meaningful.
56
+ db.exec("BEGIN IMMEDIATE");
40
57
  try {
58
+ // Re-read the gate under the lock: the PRAGMA above is a check-then-act outside any transaction.
59
+ const underLock = new Set(db.prepare("PRAGMA table_info(wallet_trust_signals)").all().map((c) => c.name));
60
+ // EACH COLUMN IS GATED INDEPENDENTLY. An earlier version added both under one gate keyed on
61
+ // `consent_state`, so a database holding one but not the other hit `duplicate column name`, the
62
+ // migration rethrew, and the daemon refused to start — a self-inflicted boot failure on a
63
+ // recoverable state. Caught by the legacy-backfill test, which constructs exactly that shape.
64
+ const needsConsent = !underLock.has("consent_state");
65
+ const needsNotified = !underLock.has("consent_notified_at");
66
+ if (!needsConsent && !needsNotified) {
67
+ db.exec("COMMIT");
68
+ return;
69
+ }
41
70
  // No DEFAULT — see the header. The rows are given their value by the explicit backfill below.
42
- db.exec("ALTER TABLE wallet_trust_signals ADD COLUMN consent_state TEXT");
43
- const res = db
44
- .prepare(`UPDATE wallet_trust_signals SET consent_state = '${CONSENT_ACCEPTED}'`)
71
+ if (needsConsent)
72
+ db.exec("ALTER TABLE wallet_trust_signals ADD COLUMN consent_state TEXT");
73
+ // DOD-END-PENDING-1 / M10B-D5 — the NOTIFICATION's lifetime, which is NOT the item's. The item
74
+ // persists until accepted or refused; the notification is raised once and stops once seen. One
75
+ // flag cannot carry both: a single seen-bit would either dismiss the pending decision (losing it)
76
+ // or re-fire on every agent selection (nagging). Two facts, two columns.
77
+ if (needsNotified)
78
+ db.exec("ALTER TABLE wallet_trust_signals ADD COLUMN consent_notified_at INTEGER");
79
+ if (!needsConsent) {
80
+ // The backfill belongs to consent_state's BIRTH. If only the notification column was missing,
81
+ // the rows already carry their consent and must not be re-judged — that is the clobber this
82
+ // file exists to prevent, and it would arrive by the back door of a partially-migrated schema.
83
+ db.exec("COMMIT");
84
+ logger.info("signal.consent.migrated", { backfilled: 0, added: "consent_notified_at" });
85
+ return;
86
+ }
87
+ // THE DIRECTION IS ENFORCED, NOT ARGUED (review F5). The header's reasoning — "everything
88
+ // predating this column is portal-issued" — is true TODAY only by release timing: the daemon has
89
+ // accepted `issuer_kind: agent` since M10, and a dev or staging wallet that picked one up during
90
+ // M10B integration testing would be backfilled straight to `accepted` and presentable, which is
91
+ // the D-23 violation this unit exists to prevent, silently, at boot. Two WHERE clauses make the
92
+ // claim a property of the code instead of a property of the calendar.
93
+ const acceptedRes = db
94
+ .prepare(`UPDATE wallet_trust_signals SET consent_state = '${CONSENT_ACCEPTED}' WHERE issuer_kind <> 'agent'`)
95
+ .run();
96
+ const pendingRes = db
97
+ .prepare("UPDATE wallet_trust_signals SET consent_state = 'pending' WHERE issuer_kind = 'agent'")
45
98
  .run();
99
+ const res = { changes: Number(acceptedRes.changes) + Number(pendingRes.changes) };
46
100
  db.exec("COMMIT");
47
101
  logger.info("signal.consent.migrated", {
48
- backfilled: Number(res.changes),
49
- to: CONSENT_ACCEPTED,
50
- reason: "rows predating consent are portal-issued — minted for the operator, at their own action",
102
+ backfilled: res.changes,
103
+ accepted: Number(acceptedRes.changes),
104
+ pending: Number(pendingRes.changes),
105
+ reason: "portal-issued rows were minted for the operator at their own action; agent-issued rows need consent",
51
106
  });
52
107
  }
53
108
  catch (err) {
54
- db.exec("ROLLBACK");
109
+ // A FAILING ROLLBACK MUST NOT MASK THE REAL ERROR (review F6, and the pattern this file claims to
110
+ // follow guards it — `contacts-tier-migration.ts` — I copied the shape minus its most important
111
+ // two lines). SQLite auto-aborts the transaction on SQLITE_FULL/SQLITE_IOERR, so a bare ROLLBACK
112
+ // then throws "cannot rollback - no transaction is active" — BEFORE the log and BEFORE the
113
+ // rethrow. The operator gets a transaction-layer message for a full disk, and
114
+ // `signal.consent.migration_failed` never fires at all.
115
+ try {
116
+ db.exec("ROLLBACK");
117
+ }
118
+ catch { /* the failing statement may already have aborted the txn */ }
55
119
  // RETHROW. A swallowed failure here leaves the daemon running against a schema it believes has
56
120
  // consent and does not — which presents unconsented endorsements while every test passes.
57
121
  logger.error("signal.consent.migration_failed", {
@@ -1 +1 @@
1
- {"version":3,"file":"consent-migration.js","sourceRoot":"","sources":["../src/consent-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAaH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE3C,MAAM,UAAU,4BAA4B,CAAC,EAAkB,EAAE,MAAc;IAC7E,MAAM,OAAO,GAAG,IAAI,GAAG,CACpB,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,EAA8B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAC5G,CAAC;IAEF,kGAAkG;IAClG,+FAA+F;IAC/F,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QAAE,OAAO;IAEzC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjB,IAAI,CAAC;QACH,8FAA8F;QAC9F,EAAE,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC1E,MAAM,GAAG,GAAG,EAAE;aACX,OAAO,CAAC,oDAAoD,gBAAgB,GAAG,CAAC;aAChF,GAAG,EAAE,CAAC;QACT,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;YACrC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;YAC/B,EAAE,EAAE,gBAAgB;YACpB,MAAM,EAAE,yFAAyF;SAClG,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpB,+FAA+F;QAC/F,0FAA0F;QAC1F,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE;YAC9C,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACzD,CAAC,CAAC;QACH,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"consent-migration.js","sourceRoot":"","sources":["../src/consent-migration.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"consortium-bootstrap.d.ts","sourceRoot":"","sources":["../src/consortium-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,qBAAqB,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,qFAAqF;IACrF,gBAAgB,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;CAC3C;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkF/F;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,qBAAqB,CAAC;IAC5C,qBAAqB,CAAC,EAAE,sBAAsB,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB,CAAC,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,uBAAuB,EAAE,MAAM,OAAO,CAAC,kBAAkB,EAAE,GAAG,IAAI,CAAC,CAAC;IACpE;;;;;OAKG;IACH,wBAAwB,EAAE,CAAC,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAChF,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC7D,qFAAqF;IACrF,oBAAoB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CAChD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAyCtF"}
1
+ {"version":3,"file":"consortium-bootstrap.d.ts","sourceRoot":"","sources":["../src/consortium-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,qBAAqB,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,qFAAqF;IACrF,gBAAgB,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;CAC3C;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkF/F;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,qBAAqB,CAAC;IAC5C,qBAAqB,CAAC,EAAE,sBAAsB,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB,CAAC,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,uBAAuB,EAAE,MAAM,OAAO,CAAC,kBAAkB,EAAE,GAAG,IAAI,CAAC,CAAC;IACpE;;;;;OAKG;IACH,wBAAwB,EAAE,CAAC,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAChF,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC7D,qFAAqF;IACrF,oBAAoB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CAChD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAoDtF"}
@@ -90,10 +90,21 @@ export function createConsortiumRouting(deps) {
90
90
  const m = manifestProvider?.getCurrentManifest();
91
91
  return m ? await manifestNodesToEndpoints(m.nodes, { logger, fetchFn }) : null;
92
92
  };
93
+ // DECLARED membership, straight off the verified manifest — no probe. Lets the resolver reject a
94
+ // primary that resolves but belongs to a different consortium (the compiled-in default URL after
95
+ // a consortium move) without mistaking a momentarily-down member for a non-member.
96
+ const getManifestPeerIds = () => {
97
+ const m = manifestProvider?.getCurrentManifest();
98
+ if (!m)
99
+ return null;
100
+ const ids = m.nodes.map((n) => n.peerId).filter((p) => typeof p === "string" && p.length > 0);
101
+ return ids.length > 0 ? new Set(ids) : null;
102
+ };
93
103
  const failoverEndpointResolver = directoryEndpointResolver
94
104
  ? createRosterAwareEndpointResolver({
95
105
  primaryResolver: directoryEndpointResolver,
96
106
  getConsortiumRoster: resolveConsortiumRoster,
107
+ getManifestPeerIds,
97
108
  logger,
98
109
  })
99
110
  : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"consortium-bootstrap.js","sourceRoot":"","sources":["../src/consortium-bootstrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"consortium-bootstrap.js","sourceRoot":"","sources":["../src/consortium-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EAKrB,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAQ7G,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAsB,MAAM,2BAA2B,CAAC;AAO5G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAkBnF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAOlD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,IAAI,oBAAoB,CAAC;IAClC;;;;OAIG;IACH,qBAAqB,IAAI,kBAAkB,CAAC;IAC5C;;;;OAIG;IACH,oBAAoB,IAAI,kBAAkB,CAAC;IAC3C;;;OAGG;IACH,iBAAiB,IAAI,eAAe,CAAC;IACrC;;OAEG;IACH,eAAe,IAAI,YAAY,CAAC;CACjC;AAYD,qBAAa,4BAA6B,YAAW,mBAAmB;IAChE,UAAU,CAAC,MAAM,EAAE,iBAAiB;CA8B3C;AAID,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAS7E"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EAKrB,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAQ7G,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAsB,MAAM,2BAA2B,CAAC;AAO5G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAkBnF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQlD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,IAAI,oBAAoB,CAAC;IAClC;;;;OAIG;IACH,qBAAqB,IAAI,kBAAkB,CAAC;IAC5C;;;;OAIG;IACH,oBAAoB,IAAI,kBAAkB,CAAC;IAC3C;;;OAGG;IACH,iBAAiB,IAAI,eAAe,CAAC;IACrC;;OAEG;IACH,eAAe,IAAI,YAAY,CAAC;CACjC;AAYD,qBAAa,4BAA6B,YAAW,mBAAmB;IAChE,UAAU,CAAC,MAAM,EAAE,iBAAiB;CA8B3C;AAID,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAS7E"}
package/dist/daemon.js CHANGED
@@ -70,6 +70,7 @@ import { registerNotificationHandlers } from "./notification-handlers.js";
70
70
  import { TypeRegistry } from "./type-registry.js";
71
71
  import { DbRegistryVersionStore } from "./registry-version-store-db.js";
72
72
  import { startRegistryPoll } from "./registry-poll.js";
73
+ import { CONSENT_ACCEPTED } from "./consent-migration.js";
73
74
  import { TrustSignalStore } from "./trust-signal-store.js";
74
75
  import { encodeCbor, decodeCbor } from "@cello-protocol/protocol-types";
75
76
  // Minimal no-op KeyProvider stub for session nodes.
@@ -1652,6 +1653,12 @@ async function startDaemonHoldingLock(config, singletonLock) {
1652
1653
  expires_at: r.expiresAt,
1653
1654
  supersedes_hash: r.supersedesHash,
1654
1655
  default_present: r.defaultPresent,
1656
+ // M10B / DOD-END-ACCEPT-1 review F4. Without this the operator cannot distinguish a signal
1657
+ // that will be presented from one awaiting their decision — or one they already refused —
1658
+ // because `default_present: true` looks identical in all three cases. `default_present`
1659
+ // answers "include it by default"; this answers the prior question, "may it be presented at
1660
+ // all".
1661
+ consent_state: r.consentState,
1655
1662
  }));
1656
1663
  return { ok: true, signals: rows };
1657
1664
  });
@@ -1689,6 +1696,7 @@ async function startDaemonHoldingLock(config, singletonLock) {
1689
1696
  schema_version: row.schemaVersion,
1690
1697
  status: row.status,
1691
1698
  default_present: row.defaultPresent,
1699
+ consent_state: row.consentState, // review F4 — see wallet_list_signals
1692
1700
  issued_at: row.issuedAt,
1693
1701
  expires_at: row.expiresAt,
1694
1702
  supersedes_hash: row.supersedesHash,
@@ -1711,6 +1719,18 @@ async function startDaemonHoldingLock(config, singletonLock) {
1711
1719
  if (!row) {
1712
1720
  return { ok: false, reason: "signal_not_found", guidance: `No wallet signal with hash prefix '${prefix}'.` };
1713
1721
  }
1722
+ // M10B / DOD-END-ACCEPT-1 review F4. Enabling a signal the subject has not accepted returned
1723
+ // `{ok: true, default_present: true}` — the daemon affirming it will now be presented, when it
1724
+ // never will. `default_present` selects from what is ELIGIBLE, and an unconsented signal is not
1725
+ // eligible; saying yes here is a hollow success on the one verb that does respond.
1726
+ if (row.consentState !== CONSENT_ACCEPTED) {
1727
+ return {
1728
+ ok: false,
1729
+ reason: "consent_pending",
1730
+ guidance: `This signal is '${row.consentState ?? "unset"}', not accepted, so it cannot be presented ` +
1731
+ "regardless of the default-present flag. Accept it first; enabling it changes nothing until then.",
1732
+ };
1733
+ }
1714
1734
  store.setDefaultPresent(row.signalHash, true);
1715
1735
  return { ok: true, signal_hash: row.signalHash, default_present: true };
1716
1736
  });
@@ -1733,6 +1753,92 @@ async function startDaemonHoldingLock(config, singletonLock) {
1733
1753
  store.setDefaultPresent(row.signalHash, false);
1734
1754
  return { ok: true, signal_hash: row.signalHash, default_present: false };
1735
1755
  });
1756
+ // ── M10B / DOD-END-SURFACE-1 — the consent verbs (D-23, M10B-D5) ───────────────────────────────
1757
+ //
1758
+ // SCOPED TO THE SELECTED AGENT, not to "the first loaded agent" the way wallet_revoke_signal is.
1759
+ // Consent is a decision the SUBJECT makes about an object a third party wrote concerning them, so
1760
+ // answering it on the wrong agent's behalf is not a cosmetic error — it is one agent deciding for
1761
+ // another. The presenting-agent pubkey is also what the store's queries scope on, and passing the
1762
+ // device-local agent_id instead now REFUSES rather than silently returning an empty queue.
1763
+ const resolveSelectedAgent = (connectionId) => {
1764
+ const name = perConnectionState.get(connectionId)?.currentAgent ?? null;
1765
+ if (!name) {
1766
+ return {
1767
+ ok: false,
1768
+ reason: "no_current_agent",
1769
+ guidance: "Select an agent first (cello_use_agent) — a consent decision belongs to the agent it is about.",
1770
+ };
1771
+ }
1772
+ const rec = loadedAgents.find((a) => a.name === name);
1773
+ if (!rec) {
1774
+ return { ok: false, reason: "agent_not_loaded", guidance: `Agent '${name}' is selected but not loaded on this daemon.` };
1775
+ }
1776
+ return { ok: true, name, pubkey: rec.pubkey };
1777
+ };
1778
+ handlers.set("consent_list_pending", async (_params, connectionId) => {
1779
+ const sel = resolveSelectedAgent(connectionId);
1780
+ if (!sel.ok)
1781
+ return sel;
1782
+ const store = new TrustSignalStore(sessionNodeManager.getDb(), logger);
1783
+ const items = store.listPendingConsent(sel.pubkey).map((r) => ({
1784
+ signal_hash: r.signalHash,
1785
+ type: r.type,
1786
+ issuer_pubkey: r.issuerPubkey,
1787
+ issued_at: r.issuedAt,
1788
+ // The payload is the ENDORSER'S OWN WORDS and is returned raw, unparsed, for the operator to
1789
+ // read before deciding. It is not interpreted here and it is never presented to anyone until
1790
+ // they accept — that is the entire point of the decision they are being asked to make.
1791
+ payload_bytes: r.payload.length,
1792
+ }));
1793
+ // Seeing the list IS being told. Marking here rather than in cello_use_agent means the operator
1794
+ // is never marked notified about something they were not actually shown.
1795
+ store.markConsentNotified(sel.pubkey);
1796
+ return { ok: true, agent: sel.name, pending: items };
1797
+ });
1798
+ handlers.set("consent_accept", async (params, connectionId) => {
1799
+ const sel = resolveSelectedAgent(connectionId);
1800
+ if (!sel.ok)
1801
+ return sel;
1802
+ const prefix = typeof params?.hash_prefix === "string" ? params.hash_prefix : null;
1803
+ if (!prefix || prefix.length < 8) {
1804
+ return { ok: false, reason: "invalid_prefix", guidance: "hash_prefix must be at least 8 hex characters." };
1805
+ }
1806
+ const store = new TrustSignalStore(sessionNodeManager.getDb(), logger);
1807
+ const item = store.listPendingConsent(sel.pubkey).find((r) => r.signalHash.startsWith(prefix));
1808
+ if (!item) {
1809
+ // Deliberately does NOT fall back to a wallet-wide lookup: a hash this agent has no pending
1810
+ // decision on is not this agent's to accept, and finding it anyway would be the cross-agent
1811
+ // decision this scoping exists to prevent.
1812
+ return { ok: false, reason: "not_pending_for_agent", guidance: `No pending consent item for '${sel.name}' with prefix '${prefix}'.` };
1813
+ }
1814
+ store.setConsentState(item.signalHash, "accepted");
1815
+ return { ok: true, signal_hash: item.signalHash, consent_state: "accepted" };
1816
+ });
1817
+ handlers.set("consent_refuse", async (params, connectionId) => {
1818
+ const sel = resolveSelectedAgent(connectionId);
1819
+ if (!sel.ok)
1820
+ return sel;
1821
+ const prefix = typeof params?.hash_prefix === "string" ? params.hash_prefix : null;
1822
+ if (!prefix || prefix.length < 8) {
1823
+ return { ok: false, reason: "invalid_prefix", guidance: "hash_prefix must be at least 8 hex characters." };
1824
+ }
1825
+ const store = new TrustSignalStore(sessionNodeManager.getDb(), logger);
1826
+ const item = store.listPendingConsent(sel.pubkey).find((r) => r.signalHash.startsWith(prefix));
1827
+ if (!item) {
1828
+ return { ok: false, reason: "not_pending_for_agent", guidance: `No pending consent item for '${sel.name}' with prefix '${prefix}'.` };
1829
+ }
1830
+ store.setConsentState(item.signalHash, "refused");
1831
+ // M10B-D4: the refusal MESSAGE back to the issuer is the subject's CHOICE and rides the
1832
+ // submission queue as an `op` — it is not sent here, and it is not sent automatically. Accepting
1833
+ // the message parameter without a carrier would be a promise this verb cannot keep, so the
1834
+ // parameter is deliberately not taken yet; the refusal itself is complete and durable.
1835
+ return {
1836
+ ok: true,
1837
+ signal_hash: item.signalHash,
1838
+ consent_state: "refused",
1839
+ note: "The issuer is not notified. Sending a refusal message requires the submission carrier (DOD-END-SUBMIT-1 wiring).",
1840
+ };
1841
+ });
1736
1842
  handlers.set("wallet_revoke_signal", async (params, _connectionId) => {
1737
1843
  const hashPrefix = typeof params?.hash_prefix === "string" ? params.hash_prefix : null;
1738
1844
  if (!hashPrefix || hashPrefix.length < 8) {