Skip to content

feat(tools): seed an approved smoke echo tool in non-production environments - #312

Merged
gibbsie merged 1 commit into
mainfrom
feat/smoke-echo-tool
Oct 12, 2026
Merged

gibbsie merged 1 commit into
mainfrom
feat/smoke-echo-tool

Conversation

@gibbsie

@gibbsie gibbsie commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Seeds an approved smoke echo tool in non-production environments via a CloudFormation custom resource in services-stack. The seeder:

  1. Uploads tools/smoke-echo-tool/index.js to TOOLS_BUCKET with SHA-256 content-hash idempotency (skips upload when the hash matches the existing S3 object's metadata tag).
  2. Creates a registry record via RegistryService (not the legacy DynamoDB tools table) and calls submitForApproval(), which auto-approves immediately when autoApproval is configured on the registry.

Prod exclusion — dual gate: CDK if (props.environment !== 'prod') omits the Lambda + custom resource from the prod template entirely; the handler itself checks ENVIRONMENT === 'prod' and exits early.

Bucket key match — seeder writes tools/smoke-echo-tool/index.js (S3_KEY = tools/${TOOL_ID}/index.js); tool-sandbox loads `tools/${toolId}/index.js` — identical pattern.

Least-privilege grants — S3: PutObject, GetObject, HeadObject on tools/* only. Registry: CreateRegistryRecord, GetRegistryRecord, ListRegistryRecords, SubmitRegistryRecordForApproval scoped to the registry ARN.

5 files changed, 14 unit tests + CDK stack assertions covering happy path, idempotency, prod exclusion, and Delete no-op.

Verification

Check Result
npx tsc --noEmit exit 0
npx jest --silent 610 suites, 9571 tests, 0 failures
npm run split:gates ALL RAILS PASSED
CI synth (ENVIRONMENT=test) exit 0, 0 cdk-nag errors
No split-baseline regeneration ✅ (no changes to split-baseline/)
No hardcoded env identifiers ✅ (grep clean)

Deployment note

Deploys with the services stack (citadel-services-{env}).

After deploy, the tool appears in Agent Tools with status APPROVED. Clicking Run with {"message":"hi"} echoes {"message":"hi","tool":"smoke-echo-tool","ts":"..."}.

Approval status: the tool seeds as APPROVED because the registry has autoApproval configured (via the registry provisioner's AutoApprovalRules). If auto-approval is later disabled, the tool will seed as PENDING_APPROVAL and must be approved once via the Approvals UI.

// --- Production exclusion ------------------------------------------------
it("skips when ENVIRONMENT is prod", async () => {
process.env.ENVIRONMENT = "prod";
await handler(makeEvent(), mockContext, jest.fn());
// --- Smoke-disabled exclusion --------------------------------------------
it("skips when SMOKE_FIXTURES_ENABLED is not true", async () => {
delete process.env.SMOKE_FIXTURES_ENABLED;
await handler(makeEvent(), mockContext, jest.fn());

// --- Delete no-op --------------------------------------------------------
it("is a no-op on Delete", async () => {
await handler(makeEvent("Delete"), mockContext, jest.fn());
status: "APPROVED",
});

await handler(makeEvent(), mockContext, jest.fn());
status: "APPROVED",
});

await handler(makeEvent(), mockContext, jest.fn());
status: "APPROVED",
});

await handler(makeEvent(), mockContext, jest.fn());
status: "APPROVED",
});

await handler(makeEvent(), mockContext, jest.fn());
status: "APPROVED",
});

await handler(makeEvent("Update"), mockContext, jest.fn());
@gibbsie
gibbsie merged commit 7db7da7 into main Oct 12, 2026
15 checks passed
@gibbsie
gibbsie deleted the feat/smoke-echo-tool branch October 12, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant