Project Info
Context-aware deception for the AI era What inspired me Most deception tooling still ships the same primitive: a lone fake credential dropped into a config file, waiting for someone to grab it. That works against a script grepping for AWS_SECRET. It fails against anything that reads context first, and increasingly the thing reading your repository is an AI agent that notices a stripe_key sitting in a folder with no billing code, no imports, and no history. An isolated honeytoken is a decoy that does not fit its own scene. I wanted the decoy to belong. If a payments repository gets a synthetic asset, it should carry that repository's vocabulary, live where a real engineer would have put it, and read as plausible enough that an agent exploring the codebase treats it as signal rather than noise. That reframing, from fake secret to believable synthetic business asset, is the whole idea. Everything else follows: infer the context, generate to fit, place where it is plausible, and detect the touch through a real monitoring pipeline instead of a mocked one. What I learned A security header can break your application in complete silence. I added a nonce-based Content-Security-Policy and the entire app stopped hydrating. No console error. No failing test. A statically prerendered page is built once with no nonce, while middleware issues a fresh one per request, and under strict-dynamic a nonce is the only thing that authorises a script, so 'self' stops applying. Every script was refused and React never took over. My first verification was wrong too: I read server-rendered form inputs as proof the client was alive. The only trustworthy signal turned out to be comparing the nonce in the served HTML against the one in the response header. That comparison is now a CI check. Expiry checks are security checks, and they fail like security checks. Writing sandbox tests surfaced a latent bug: authenticating an expired API key compared a naive stored timestamp against an aware one and raised TypeError. An expired key returned 500 instead of 401. Harmless until judge credentials, which always carry an expiry, made it reachable. Documentation that contradicts enforced behaviour is an operational defect, not stale prose. Several documents told operators the opposite of what startup validation enforced: REDIS_FAIL_MODE=open described as permitted, disabled auth described as merely rejected per request when it now refuses to boot. An operator following them would produce a deployment that does not start. I reversed an earlier architecture decision record rather than rewriting it, because an ADR records what was decided and why it changed. Configuration leaks through .env. Enabling one feature flag locally broke six unrelated production tests, because pydantic-settings reads that file and the value reached assertions that construct settings directly. Deriving the hardened-mode set from a single exported constant, instead of a copy-pasted literal, removed a whole class of drift. The through-line: in a security tool the dangerous failures are the quiet ones. The work was not making features exist. It was making the guarantees provable, on real HTTP responses, against a running system, in CI. How I built it A monorepo: FastAPI backend, Next.js dashboard, Plasmo browser extension, shared contracts package. The pipeline is a straight line you can watch end to end: scan → context → placement → generation → validation → monitoring → alert → incident Analysis is deterministic. It runs over bounded structured signals — languages, frameworks, services, naming patterns, sensitive-zone categories, AI surfaces — never raw source. Path-like values are descriptive metadata; the backend never opens them. Every inference reports its supporting evidence and a confidence value, so a reviewer sees why, not only what. Detection is signed and fails closed. Monitoring ingestion uses an HMAC scheme with a replay-nonce store and organization-scoped rate limiting. A touched decoy emits a signed event; the event becomes an alert only after verification; the incident is reconstructed from stored evidence rather than asserted. Severity and timeline come from application logic. GPT does two bounded jobs. It drafts synthetic content matching the inferred context, and turns a verified timeline into analyst-readable prose. It decides nothing that matters: not severity, not deployment, not whether an incident occurred. When the model is unavailable a deterministic fallback runs, and the interface labels it as such. Calibration uses Wilson score intervals rather than raw acceptance fractions, so a decoy accepted 3 of 3 times does not outrank one accepted 40 of 45. For observed acceptance $\hat{p} = x/n$ at confidence $z$, ranking trusts the lower bound $$ w^{-} = \frac{\hat{p} + \dfrac{z^{2}}{2n} - z\sqrt{\dfrac{\hat{p}(1-\hat{p})}{n} + \dfrac{z^{2}}{4n^{2}}}}{1 + \dfrac{z^{2}}{n}} $$ so small samples are penalised honestly and a cohort needs real evidence before it moves a weight. Anti-poisoning thresholds cap any single actor's contribution, and no learned weight reaches production without human approval. Deployment modes let one codebase serve as local development, a hosted evaluation sandbox, or a locked-down production tenant. APP_ENV is a closed set, so a typo fails startup instead of silently selecting middle behaviour. The hosted judge mode is production-hardened and differs only in which demonstration surfaces mount. Each evaluator receives a TTL-bound sandbox with its own generated organization, so no one can see another's work. Codex worked alongside me across implementation, migrations, tests, tenant-isolation and signed-ingestion review, CI debugging, and hardening. It was genuinely fast at mechanical breadth: wiring a router, drafting a migration, generating negative-path tests. It decided nothing load-bearing. Product direction, security boundaries, human-approval requirements, and final acceptance stayed mine. The pattern that earned its keep was adversarial: Codex proposes, I verify against the running system before believing it. Challenges I ran into One symptom, three unrelated causes. The judge workspace froze on its loading state. First cause: the nonce CSP blocking prerendered scripts. Second: next dev runs hot reload through eval and emits inline scripts with an empty nonce, and because a CSP containing a nonce makes browsers ignore 'unsafe-inline', my first fix did nothing at all. Third: two development servers sharing one build directory clobbered each other's chunks, so the page rendered correctly on the server and never hydrated. Identical symptom, no console error in any of the three. I found the last one only by counting attached React fibers between two servers running the same code: 21 on one, 0 on the other. Making the demo safe to host. The demo routes had no authorization at all. Fine while they were development-only; the moment a hosted evaluation mode could mount them, five mutating endpoints became unauthenticated writes on an internet-reachable deployment. Splitting reads open and writes credentialed took more thought than expected: requiring a credential to look at a fixed fictional story buys nothing, but letting anyone reshape what every other viewer sees is a real problem. Proving isolation instead of asserting it. It is easy to claim a sandbox cannot read files. Demonstrating it took a test that writes a marker into a real file, passes its path as a descriptive signal, and asserts the marker never appears in the response. If the backend had opened it, the analysis could leak the contents. Most of the isolation suite is shaped that way, and nearly all of its assertions are negative. Knowing when my own verification was insufficient. More than once I declared something working on evidence that did not support the claim. Server-rendered HTML mistaken for hydration. A contract test that silently went hollow after a refactor moved the string it matched. Catching those mattered more than any single feature, because a security tool whose guarantees are unverified is just a tool with confident documentation. What is next Repository and context metadata is still plaintext at rest while alerts and incidents are encrypted. Closing that gap is the next real change. Beyond it: a hosted deployment with restore-drill evidence, and widening the calibration engine from bounded demonstration toward measured, human-approved production use.
DeceptiForge
Context-aware deception for the AI era
DeceptiForge analyzes repository and organizational signals, proposes believable synthetic business assets, explains where they should be placed, and reconstructs an incident when those assets are touched.
OpenAI Build Week category: Developer Tools.
Public video: https://youtu.be/8HOHHayxvO4
Hosted judge workspace: Distributed to judges through the submission channel. Its URL and credentials are intentionally not committed to this repository.
Problem
Conventional honeytokens can be useful, but a generic credential often looks disconnected from the repository, documentation, and business workflow where it appears. That problem is more visible when engineers, coding agents, retrieval systems, and operational services encounter the same internal material.
Approach
DeceptiForge normalizes repository and organizational signals such as technologies, naming conventions, documentation zones, infrastructure indicators, databases, and AI-facing surfaces. It builds a context profile, ranks sensitive zones, recommends plausible placements, and evaluates synthetic assets for safety and believability.
When a registered trace is observed, deterministic services validate the event, minimize evidence, create a deduplicated alert, and reconstruct an incident timeline. The core flow is Context → Decoy → Placement → Detection → Incident.
Implemented features
- Repository intelligence, naming-pattern inference, organization context, sensitive-zone ranking, and explainable placement reasoning.
- Template-constrained secret, document, and database-record decoy concepts with deterministic safety and believability assessment.
- Trace registration, signed monitoring ingestion, replay protection, normalized alerting, deduplication, deterministic incident reconstruction, and bounded evidence.
- Organization-scoped API keys, roles, permissions, audit records, payload limits, and Redis-backed distributed replay and rate-limit controls.
- A restricted judge workspace with a TTL-bound fictional organization, per-session quotas, safe export, and reset isolation.
- An Interactive Analysis Lab for development and test, with ten fictional structured-signal scenarios, comparison, and JSON or Markdown export.
Feature-flagged deployment workflows, database honey records, AI/browser/agent sensors, measured coverage, SIEM export, reliability, and capacity controls are disabled by default and covered with deterministic fakes where applicable. They are not a claim of production certification.
Architecture
Next.js provides the dashboard; FastAPI hosts the deterministic security pipeline. PostgreSQL stores organization-scoped artifacts, while Redis provides distributed replay and rate-limit state in hardened modes. Reconstruction is queued so ingestion remains on the hot path. GPT is optional and cannot change authoritative security facts.
How GPT-5.6 Is Used
The runtime integration is model-configurable. It can use an approved OpenAI model to turn an already verified, deterministic incident timeline into an analyst-readable narrative. Input is minimized and sanitized, output is schema-validated and bounded, and model failure, missing credentials, or invalid output falls back to a deterministic narrative.
The current checked-in default is gpt-5.6, the GPT-5.6 Sol alias. Verify the rendered model badge in the recording before claiming GPT-5.6 on Devpost.
GPT does not assign severity, authorize deployment, accept monitoring events, alter evidence, choose an organization, or determine that an incident exists. Decoy generation is deterministic in the current implementation. A concrete demo example is a repository-trace touch that still produces its event, alert, severity, and incident when model access is disabled; only the analyst prose falls back.
How We Built DeceptiForge with Codex
Codex accelerated codebase navigation, backend and frontend implementation, typed contract design, tests, migrations, tenant-isolation and signed-ingestion review, CI troubleshooting, dependency and container hardening, demo reliability, and documentation reconciliation.
The project author chose the security problem and context-aware deception thesis, required deterministic authority and human approval boundaries, rejected unsafe filesystem and hosted-demo shortcuts, selected the route model, and reviewed, revised, and tested generated changes. Codex was used to build and refine the project; it did not independently set product policy or security authorization.
What We Added During OpenAI Build Week
The repository predates Build Week. The following verifiable extensions were added or substantially revised from July 13 through July 21, 2026:
- Platform-scope authorization separation, tenant-isolation coverage, signed-ingestion hardening, Redis fail-closed behavior, and production-shaped security tests.
- Interactive Analysis Lab and deterministic scenario comparison, added July 20 (
537fd80,fdc2123). - Dependency lockfiles, container and CI hardening, production topology validation, and operational worker readiness, added July 21 (
d561d80,f319daa,54a5157). - Explicit development, judge, staging, and production deployment modes; a restricted judge workspace; TTL-bound sandbox credentials; quotas; safe export; and isolated reset, added July 21 (
95903a5,3e7c0ef,5f93967,f4ade8c,5d327be).
These commits are evidence of meaningful extension during the event period; they do not imply that the entire project was created during Build Week.
Codex Session ID
Codex Session ID: 019f67eb-fa4d-77d0-ad70-eb034c57d246
Quick start
Prerequisites
- Docker Desktop with Compose
- Node.js compatible with pnpm 9.15.4 and pnpm 9.15.4
- Python 3.12+ for local API tooling
git clone <repository-url>
cd DeceptiForge
cp .env.example .env
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env.local
pnpm install
docker compose up --build -d
docker compose exec api alembic upgrade head
pnpm --filter @deceptiforge/web dev
Open http://localhost:3000. The development templates enable fictional demo data. Select Run DeceptiForge Demo, then confirm the context, placement, synthetic validation, event, alert, incident, and narrative. A local smoke check is curl http://localhost:8000/health.
For detailed environment, API, and deployment instructions, see Development, Pipeline API, and Deployment.
Judge testing
Use the hosted judge URL supplied through the submission channel, not localhost. Use a current Chromium browser.
- Receive a dedicated organization ID and API key through a trusted channel.
- Open the root workspace and choose a fictional scenario.
- Inspect the inferred context, sensitive zones, placement reasoning, and synthetic decoy concept.
- Trigger the controlled interaction, then inspect the deterministic event, alert, incident, and evidence summary.
- Review the analyst narrative and its deterministic fallback boundary.
- Reset the sandbox. Reset affects only that sandbox and does not restore spent quota.
Judge credentials are provisioned out of band, shown once, organization-bound, and time-limited. A sandbox expires with HTTP 410; an operator must issue a new one. See Judge access runbook. The sandbox uses fictional data, accepts bounded structured signals only, disables production connectors, and never scans a local path or clones a repository.
The curated /demo story is development/judge-only. /analysis-lab is development/test-only and returns 404 elsewhere.
Installing the sensors (developer tools)
Two components install into a developer's own environment. Both are disabled by default: their routers do not mount until the server flag is set, so the endpoints return 404 until then.
Browser extension (AI-paste sensor)
Server: set BROWSER_SENSOR_ENABLED=true.
pnpm --filter @deceptiforge/extension build # -> apps/extension/build/chrome-mv3-prod
Chrome: chrome://extensions -> enable Developer mode -> Load unpacked -> select
apps/extension/build/chrome-mv3-prod. Chrome MV3 only; Firefox is not supported, and the
extension is not published to the Web Store.
It requests storage and alarms and nothing else, with host access scoped to the supported AI
surfaces. Each install enrolls with a one-time short-lived token that exchanges for a scoped ingest
credential, never a dashboard key. Matching is local against hashed trace tokens; pasted text,
prompts, and model responses are never transmitted or stored.
Agent adapter SDK and CLI
Server: set AGENT_SENSOR_ENABLED=true. Detect-only by default (AGENT_SENSOR_MODE=detect).
Enroll first: an admin creates a one-time token (POST /agent-sensors/enrollment-tokens) which the
wrapper exchanges (POST /agent-sensors/enroll) for a sensor identity, a scoped signing secret, and
an agent_sensor ingest key.
# Credentials come from the environment, never from arguments:
# DECEPTIFORGE_URL / _ORG_ID / _API_KEY / _SENSOR_ID / _SENSOR_SECRET
python -m app.agent_sdk.cli start --session-id S --agent-type claude-code \
--task "Fix navbar" --allow "apps/web/**"
echo '{"id":"e1","event_type":"file_read","path":"apps/web/navbar.tsx"}' \
| python -m app.agent_sdk.cli event --session-id S --adapter jsonl
python -m app.agent_sdk.cli finish --session-id S
The CLI does not run your agent; it reports observed events alongside one. Raw content (file contents, command output, prompts, reasoning, SQL) is stripped before an event leaves the process.
Testing path for judges
cd apps/api && python -m pytest # backend suite
pnpm typecheck && pnpm lint && pnpm test
pnpm --filter @deceptiforge/extension build
Confirm the sensors are gated before enabling them:
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8000/browser-sensors # 404 while off
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8000/agent-sensors # 404 while off
CI additionally fails the build on any forbidden extension permission, any eval/new Function,
any remote script URL, or any embedded secret in the built MV3 bundle.
Supported platforms
- Tested: macOS, Docker Desktop, Python 3.12, PostgreSQL 16, Redis 7, Node.js with pnpm 9.15.4, and Chrome for the local dashboard.
- Reasonably supported: current Chromium browsers on Linux and Windows, including Docker through WSL2.
- Untested: other operating systems and non-Chromium browsers. They are not claimed as certified.
Security and privacy boundaries
Demo and judge assets are fictional and synthetic. API keys are organization-bound; tenant actors cannot mint platform or judge roles. Hardened modes require signed monitoring ingestion, distributed replay protection, and fail-closed Redis behavior. Evidence is minimized, and model input excludes raw payloads.
The development demo drives the deterministic pipeline in-process, not through a registered signed-monitor HTTP client. Signed ingestion is separately implemented and tested; the demo should not be represented as proving that boundary end to end.
Current limitations
DeceptiForge is a controlled staging and judge-sandbox project, not a production-certified security service. Current limitations include no live GitHub/GitLab provider, no complete user OAuth/SSO implementation, no API-key rotation workflow, and no legal-hold implementation. GPT-assisted narratives are optional; all detection and incident decisions have deterministic fallback.
Detailed documentation
- Architecture, Security model, and Production readiness
- Development, Deployment, and Judge access
- Pipeline API, Incident narrative, and Disaster recovery
License
Analysis
View
Metric
- 157
- 109
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- FastAPIIn code
- Next.jsIn code
- PythonIn code
- ReactIn code
- RedisIn code
- Tailwind CSSIn code
- TypeScriptIn code
- PostgreSQLClaimed
8 of 9 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeCommits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
2.8 MB
Source files
598
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
akulhada/DeceptiForge
649 files · 3.0 MB · @ c552df2
Structure
Interface
39 files · 6%Screens, components and styles rendered to the user.
API & routing
177 files · 27%Request entry points: routes, handlers and controllers.
Application logic
64 files · 10%Domain rules, services and shared utilities.
Background jobs
11 files · 2%Work run outside a request: tasks, workers and schedules.
Data & schema
73 files · 11%Schema definitions, migrations and data access.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python65%
- TypeScript15%
- YAML11%
- Markdown8%
- Shell1%
- CSS0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
apps/web/package.json
npm · 19- @deceptiforge/contracts
- @radix-ui/react-slot
- class-variance-authority
- clsx
- lucide-react
- next
- react
- react-dom
- tailwind-merge
- +10 more
apps/api/pyproject.toml
pypi · 14- alembic
- cryptography
- fastapi
- httpx
- psycopg[binary]
- pydantic-settings
- redis
- sqlalchemy
- uvicorn[standard]
- +5 more
apps/extension/package.json
npm · 11- react
- react-dom
- +9 more
packages/contracts/package.json
npm · 55 development-only dependencies.
package.json
npm · 22 development-only dependencies.
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.