Skip to content

Commit 420233a

Browse files
Branimir Rakiccursoragent
authored andcommitted
fix(daemon): Codex PR #595 round-2 — explicit deprecation for legacy multisig-only /create body
Pre-LU2 the route had a dedicated branch that accepted `{ participantIdentityIds, requiredSignatures }` (no id/name) and called `agent.registerContextGraphOnChain()` directly. LU-2 deleted that branch but only stripped the dead fields, so legacy multisig-only callers silently fell through to "Missing id or name" — a misleading 400 that hides the fact that the entire flow was retired in SPEC_CG_MEMORY_MODEL. Now those callers get an explicit 400 with code `DEPRECATED_MULTISIG_CREATE_FLOW` pointing at the new `{ id, name, ... }` + optional `/api/context-graph/register` flow. Modern clients that send the deprecated fields alongside a valid `{ id, name }` body keep working (warned + stripped) as before. Two HTTP-level tests pin both branches: - modern body with deprecated extras still creates the CG - legacy multisig-only body returns the explicit deprecation error Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 05ba0d1 commit 420233a

2 files changed

Lines changed: 70 additions & 7 deletions

File tree

packages/cli/src/daemon/routes/context-graph.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -425,17 +425,33 @@ export async function handleContextGraphRoutes(ctx: RequestContext): Promise<voi
425425

426426
// POST /api/context-graph/create — context graph definition create.
427427
// LU-2: per SPEC_CG_MEMORY_MODEL the legacy multisig-creation branch
428-
// (driven by a `participantIdentityIds`-only body) is gone. CGs no
429-
// longer carry per-CG hosting committees or quorum overrides; hosts
430-
// are picked from the network sharding table at publish time and the
431-
// ACK quorum is `parametersStorage.minimumRequiredSignatures()`. We
432-
// accept the legacy body for backward compatibility but drop the dead
433-
// fields with a one-line deprecation warning so older clients keep
434-
// working.
428+
// (driven by a `participantIdentityIds`-only body, no id/name) is gone.
429+
// CGs no longer carry per-CG hosting committees or quorum overrides;
430+
// hosts are picked from the network sharding table at publish time
431+
// and the ACK quorum is `parametersStorage.minimumRequiredSignatures()`.
432+
//
433+
// Two client groups exist for these deprecated fields:
434+
// (a) modern clients that send the full `{ id, name, participantIdentityIds, requiredSignatures }`
435+
// body — we strip the dead fields and continue.
436+
// (b) legacy multisig-only clients that send `{ participantIdentityIds, requiredSignatures }`
437+
// with no `id`/`name` — there is no automatic translation that
438+
// preserves caller intent (we can't synthesise a meaningful slug),
439+
// so we fail with an explicit 410-style deprecation error pointing
440+
// at the new combined flow instead of letting the request fall
441+
// through to a generic "Missing id or name" 400.
435442
if (req.method === "POST" && path === "/api/context-graph/create") {
436443
const body = await readBody(req, SMALL_BODY_BYTES);
437444
const parsed = JSON.parse(body);
438445
if (parsed.participantIdentityIds !== undefined || parsed.requiredSignatures !== undefined) {
446+
const isLegacyMultisigOnly =
447+
typeof parsed.id !== 'string' && typeof parsed.name !== 'string';
448+
if (isLegacyMultisigOnly) {
449+
return jsonResponse(res, 400, {
450+
error:
451+
'The multisig-only POST /api/context-graph/create flow (participantIdentityIds without id/name) was removed in SPEC_CG_MEMORY_MODEL. Per-CG hosting committees and per-CG quorum overrides no longer exist. Send a regular `{ id, name, accessPolicy?, publishPolicy? }` body and (if you want chain registration) follow up with POST /api/context-graph/register.',
452+
code: 'DEPRECATED_MULTISIG_CREATE_FLOW',
453+
});
454+
}
439455
console.warn(
440456
'[DKG-Daemon] WARN: POST /api/context-graph/create — `participantIdentityIds` and `requiredSignatures` are deprecated and ignored; per-CG hosting committees and quorums were removed in SPEC_CG_MEMORY_MODEL.',
441457
);

packages/cli/test/daemon-http-behavior-extra.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,53 @@ describe('CLI-7 — SPARQL endpoint 4xx matrix', () => {
724724
// message — callers should see something human-readable.
725725
expect(body.error).not.toMatch(/^0x[0-9a-fA-F]+$/);
726726
});
727+
728+
// SPEC_CG_MEMORY_MODEL / Codex PR #595 round-2: per-CG hosting
729+
// committees and per-CG quorum overrides were removed. Two paths
730+
// exist for legacy clients:
731+
// (a) modern `{ id, name, ...deprecated }` body — the daemon
732+
// strips the dead fields and the request succeeds.
733+
// (b) legacy multisig-only `{ participantIdentityIds, requiredSignatures }`
734+
// body with no `id`/`name` — pre-LU2 there was a dedicated
735+
// branch that bypassed id/name; post-LU2 we MUST fail with an
736+
// explicit deprecation error pointing at the new combined flow
737+
// rather than silently falling through to the generic
738+
// "Missing id or name" 400 (which doesn't tell the caller
739+
// their request shape was retired).
740+
it('strips deprecated participantIdentityIds/requiredSignatures from a modern body and still creates the CG', async () => {
741+
const d = daemon!;
742+
const cgId = 'depr-fields-modern-' + Math.random().toString(36).slice(2, 8);
743+
const res = await fetch(urlFor(d, '/api/context-graph/create'), {
744+
method: 'POST',
745+
headers: { 'Content-Type': 'application/json', ...authHeaders(d) },
746+
body: JSON.stringify({
747+
id: cgId,
748+
name: cgId,
749+
participantIdentityIds: ['1', '2', '3'],
750+
requiredSignatures: 2,
751+
}),
752+
});
753+
expect([200, 201]).toContain(res.status);
754+
const body = (await res.json()) as { created?: string };
755+
expect(body.created).toBe(cgId);
756+
});
757+
758+
it('rejects legacy multisig-only POST /api/context-graph/create (no id/name) with an explicit deprecation 400', async () => {
759+
const d = daemon!;
760+
const res = await fetch(urlFor(d, '/api/context-graph/create'), {
761+
method: 'POST',
762+
headers: { 'Content-Type': 'application/json', ...authHeaders(d) },
763+
body: JSON.stringify({
764+
participantIdentityIds: ['1', '2'],
765+
requiredSignatures: 1,
766+
}),
767+
});
768+
expect(res.status).toBe(400);
769+
const body = (await res.json()) as { error?: string; code?: string };
770+
expect(body.code).toBe('DEPRECATED_MULTISIG_CREATE_FLOW');
771+
expect(body.error ?? '').toMatch(/SPEC_CG_MEMORY_MODEL/);
772+
expect(body.error ?? '').toMatch(/id.*name/);
773+
});
727774
});
728775

729776
describe('DKG-419 — lazy context graph metadata from SWM writes', () => {

0 commit comments

Comments
 (0)