From 64ce4b6e7b66d859b8a7fb6b8b717dd47694440a Mon Sep 17 00:00:00 2001 From: Nick Bianchi Date: Tue, 17 Mar 2026 00:01:30 +0000 Subject: [PATCH] =?UTF-8?q?fix(auth):=20correct=20entity=20type=20T?= =?UTF-8?q?=E2=86=92P=20for=20context=20ChittyIDs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChittyMint ignores the entity_type=P parameter and always returns T (Thing). Contexts are Person (P) per canonical governance (chittycanon://gov/governance#core-types). This client-side correction: - Detects entity type mismatch after minting - Replaces T with P in the ChittyID segment - Recalculates mod-97 checksum for the corrected ID - Persists the minted ChittyID even when ChittyCanon DB is unavailable (previously fell back to "UNBOUND" losing the minted ID) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/commands/hook-handlers.ts | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/commands/hook-handlers.ts b/src/commands/hook-handlers.ts index ef5fcc4..e6d8d27 100755 --- a/src/commands/hook-handlers.ts +++ b/src/commands/hook-handlers.ts @@ -559,15 +559,29 @@ export async function handleAuthenticateContext(args: string[]): Promise { }); if (chittyId) { + // @canon: chittycanon://gov/governance#core-types — contexts are Person (P), not Thing (T) + // ChittyMint currently ignores entity_type param; correct it client-side until upstream fix + const segments = chittyId.split("-"); + let correctedId = chittyId; + if (segments[4] && segments[4] !== "P") { + console.log(` \x1b[33m⚠ Entity type mismatch: got '${segments[4]}', expected 'P' (Person) — correcting\x1b[0m`); + segments[4] = "P"; + // Recalculate checksum (mod-97 of all segments except last) + const baseSegments = segments.slice(0, -1); + const numericStr = baseSegments.join("").replace(/[A-Z]/g, (c) => String(c.charCodeAt(0) - 55)); + const checksum = String(98n - (BigInt(numericStr) % 97n)).padStart(2, "0"); + segments[segments.length - 1] = checksum; + correctedId = segments.join("-"); + } // Create context in database - context = await createContextInDb(chittyId, { + context = await createContextInDb(correctedId, { projectPath, workspace, supportType, organization, anchorHash }); - console.log(` \x1b[32m✓ New context minted: ${chittyId}\x1b[0m`); + console.log(` \x1b[32m✓ New context minted: ${correctedId}\x1b[0m`); } else { // Fallback: create local-only binding console.log(` \x1b[33m⚠ Session UNBOUND - ChittyConnect unreachable\x1b[0m`); @@ -816,7 +830,8 @@ async function createContextInDb(chittyId: string, anchors: { anchors.projectPath, anchors.workspace, anchors.supportType, - anchors.organization + anchors.organization, + chittyId ); } @@ -875,7 +890,8 @@ async function createContextInDb(chittyId: string, anchors: { anchors.projectPath, anchors.workspace, anchors.supportType, - anchors.organization + anchors.organization, + chittyId ); } } @@ -888,10 +904,11 @@ function createLocalContext( projectPath: string, workspace: string | null, supportType: string, - organization: string | null + organization: string | null, + mintedChittyId?: string ): ContextBinding { return { - chittyId: "UNBOUND", + chittyId: mintedChittyId || "UNBOUND", contextId: "", anchorHash, projectPath,