{"record":{"id":"b831c188e72fd307","repo":"astrid-runtime/astrid","slug":"mcp-attach-registration-is-missing-hook-token","errorCode":null,"errorMessage":"MCP attach registration is missing hook_token","messagePattern":"MCP attach registration is missing hook_token","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/gateway.rs","lineNumber":934,"sourceCode":"    Ok(request)\n}\n\nfn validate_registration(registration: &AttachRegistration) -> Result<()> {\n    if registration.version != ATTACH_REGISTRATION_VERSION {\n        anyhow::bail!(\n            \"unsupported MCP attach registration version {}\",\n            registration.version\n        );\n    }\n    super::lifecycle::resolve_principal(Some(&registration.principal))?;\n    if registration.host.trim().is_empty() {\n        anyhow::bail!(\"MCP attach registration has an empty host\");\n    }\n    if registration.host_session_id.trim().is_empty() {\n        anyhow::bail!(\"MCP attach registration has an empty host_session_id\");\n    }\n    if registration.hook_token.trim().is_empty() {\n        anyhow::bail!(\"MCP attach registration is missing hook_token\");\n    }\n    validate_workspace(&registration.workspace_abs)?;\n    Ok(())\n}\n\nfn authenticate_registration(\n    registration: &AttachRegistration,\n    state: &GatewayState,\n) -> Result<astrid_core::PrincipalId> {\n    let principal = super::lifecycle::resolve_principal(Some(&registration.principal))?;\n    if principal != state.principal {\n        anyhow::bail!(\n            \"MCP attach registration principal '{}' is not the authenticated gateway principal '{}'\",\n            principal,\n            state.principal\n        );\n    }\n    if registration.hook_token != state.hook_token {","sourceCodeStart":916,"sourceCodeEnd":952,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/gateway.rs#L916-L952","documentation":"validate_registration requires every attach registration to carry a hook_token, a shared secret minted by the gateway that authenticates subsequent requests. A missing (empty/whitespace-only) hook_token is rejected before any uplink selection or workspace validation happens. This prevents unauthenticated attaches from proceeding further into gateway state.","triggerScenarios":"Sending an AttachRegistration via the MCP attach request path with hook_token empty or absent; creating the registration struct manually without copying the token from the gateway startup lease/ready record.","commonSituations":"Client never read the gateway readiness metadata containing hook_token; placeholder left empty in a config file; token field dropped during payload serialization; tests constructing AttachRegistration by hand.","solutions":["Populate hook_token from the gateway's minted token (startup lease / readiness record) before attaching","Verify the readiness file was read successfully and its hook_token field copied into the registration","Regenerate/restart the gateway if the token was lost and re-read the readiness metadata","Log the registration payload (minus secrets) to confirm which field is empty"],"exampleFix":"// before\nhook_token: String::new(),\n// after\nhook_token: ready_record.hook_token.clone(),","handlingStrategy":"validation","validationCode":"if reg.hook_token.trim().is_empty() { return Err(\"hook_token is required: read the gateway readiness record first\"); }","typeGuard":"fn has_hook_token(reg: &AttachRegistration) -> bool { !reg.hook_token.trim().is_empty() }","tryCatchPattern":null,"preventionTips":["Read the readiness record and clone its hook_token into every registration","Never construct AttachRegistration with String::new() defaults","Rotate client code when gateway token format changes"],"tags":["validation","mcp","authentication"],"backgroundTag":"missing-credentials","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}