# Project export: Scope Guard

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: Intent-bound execution for safer AI-powered development and deployment, let coding agents move fast without letting them wander.
- Devpost: https://devpost.com/software/scope-guard
- GitHub: https://github.com/gethsun1/scope-guard
- Demo: https://scopeguard-vert.vercel.app/
- Video: https://www.youtube.com/embed/RBQiJZXyf4Q?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Gethsun1 (17 commits)

## Devpost submission (written by the team)

### Inspiration

Scope Guard came from a problem I have repeatedly faced while working with coding agents in real development environments. I often manage several projects at the same time, sometimes on the same machine or server. Each project may have its own repository, database, service, port, environment variables, deployment configuration, and domain. When I ask a coding agent to work on one application, the task may sound simple: Update this project, run the migration, restart the service, and verify the deployment. The problem is that an agent does not always understand the operational boundaries that are obvious to the developer. A command can be technically valid and still target the wrong service. A configuration change can fix one application while breaking another. A deployment script can restart a shared dependency, read an unrelated environment file, or modify a project that was never part of the original request. I experienced this concern while working with projects such as RD Social and EngageFlow. Both applications had different responsibilities, but they could exist within the same broader infrastructure. Whenever I gave an agent access to help with deployment or debugging, I found myself repeatedly adding instructions such as: Work only on RD Social. Do not modify EngageFlow. Do not restart unrelated services. Do not touch any other database or configuration. That made me realize that the real issue was not simply sandboxing. Traditional sandboxing asks: What can the agent technically access? The question I wanted Scope Guard to answer was: Does this specific action belong to the task the developer actually approved? That distinction became the foundation of the project. What Scope Guard Does Scope Guard is an intent-bound execution control plane for coding agents. It converts a developer's natural-language task into a structured project boundary containing: Allowed repositories and filesystem paths Protected projects and configuration files Approved services and containers Databases Ports and domains Operations requiring human approval Actions that must always be blocked Once the boundary is approved, every proposed action is evaluated before it is executed. Scope Guard can return one of several deterministic decisions: ALLOW ALLOW_WITH_APPROVAL BLOCK_OUT_OF_SCOPE BLOCK_PROTECTED_RESOURCE BLOCK_DESTRUCTIVE BLOCK_UNKNOWN_RESOURCE BLOCK_SECRET_ACCESS BLOCK_NETWORK_DESTINATION BLOCK_POLICY_AMBIGUITY The language model can interpret intent, propose a plan, explain risks, and suggest corrections, but it does not make the final security decision. That responsibility belongs to a deterministic policy engine. This separation was one of the most important design choices in the project: GPT-5.6 helps Scope Guard understand the task. The policy engine decides what is permitted. The Demonstration Scenario I built the project around a synthetic shared-server scenario containing two applications: RD Social The target project that the agent is allowed to update and deploy. EngageFlow A separate protected project that must remain healthy and unchanged. The developer submits the task: Update and deploy RD Social, run its approved migration, restart its API, and verify its health without modifying EngageFlow. GPT-5.6 interprets the request and produces a structured boundary and execution plan. Codex then proposes the development and deployment actions. During the demonstration, the agent attempts to restart the EngageFlow service. Scope Guard detects that the service belongs to a protected project and blocks the operation before execution. The rejection includes: The blocked command The affected protected resource The policy rule that was violated A human-readable explanation A structured machine-readable explanation A suggested corrected action The Codex workflow then receives that rejection context and revises the plan to restart the correct RD Social service. The corrected operation proceeds through an approval gate. Scope Guard creates a snapshot before the mutation, applies the approved change, runs health checks, and verifies that EngageFlow remained unchanged. The demonstration also injects a deliberate RD Social failure. Scope Guard detects the failed health check, restores the target project's previous state, and verifies that the protected EngageFlow application was never modified during execution or rollback. How I Built It Scope Guard is implemented as a monorepo with a clear separation between the user interface, orchestration layer, policy engine, agent integrations, evaluation suite, and synthetic execution environment. Frontend I built the control plane using: Next.js TypeScript Tailwind CSS Typed API validation Responsive layouts Real-time execution events The interface is intentionally designed as a developer operations dashboard rather than a generic chat application. It includes six main product areas: Overview dashboard Environment inventory Guarded task creation Boundary review Live execution and approvals Reports and SentryBench results The most important screen is the blocked-action view. It makes the reason for a policy rejection understandable without requiring the developer to inspect raw logs. Backend The orchestration layer is built with: FastAPI Python Pydantic Structured API contracts Server-side event streaming Typed task and policy models The backend manages: Task creation Environment inventory Boundary generation Boundary approval Agent action proposals Policy evaluation Human approvals Execution events Snapshots Validation Rollback Reports GPT-5.6 I integrated GPT-5.6 as the planning and interpretation layer. It receives: The developer's task The available infrastructure inventory Resource relationships Existing constraints Supported operations It returns structured information including: Interpreted intent Target project Allowed resources Protected resources Proposed steps Risk summary Validation plan Rollback plan Confidence All model output is validated against strict schemas before it can enter the execution workflow. GPT-5.6 is never treated as the final authority. A plausible explanation from the model cannot override a deterministic block. Codex Codex played two roles in the project. First, I used Codex extensively to accelerate the implementation itself. It helped scaffold the monorepo, build the policy engine, create the synthetic environment, write tests, refine the frontend, improve documentation, and repeatedly verify the full workflow. Second, Scope Guard includes a Codex integration layer that can receive coding-agent proposals and pass them through the policy engine. The guarded flow is: This allows the agent to remain useful without allowing it to silently expand its own permissions. Synthetic Docker Environment I did not test Scope Guard against my live projects. Instead, I created a Docker-only synthetic environment that models the operational relationship between RD Social and EngageFlow. The environment runs with: Non-root users No host Docker socket No privileged containers Restricted mounts No production credentials No access to real databases No connection to production infrastructure The runner operates as UID 10001, with zero effective Linux capabilities and NoNewPrivs enabled. This was important because a project about agent safety should also demonstrate disciplined isolation during its own development. Deterministic Enforcement One of the biggest challenges was avoiding security theatre. It would have been easy to ask a language model whether a command looked safe and display its answer. That would create an attractive demonstration, but it would not create an enforceable boundary. I therefore separated the system into distinct stages: The command-analysis layer identifies: Filesystem paths Relative path escapes Service names Database names Ports Domains Environment files Network destinations Destructive shell operations Secret access patterns The policy engine then compares those resources against the approved boundary manifest. Unknown resources are denied by default. The language model can suggest that an action is safe, but the policy engine can still block it. Snapshots, Validation, and Rollback Blocking unsafe actions is only part of the problem. A valid in-scope action can still fail. Before a mutating action, Scope Guard records: Relevant file hashes Repository state Service state Health-check state Migration state Protected-resource integrity state After execution, it validates both sides of the boundary. For the target project, it checks whether the expected deployment succeeded. For the protected project, it verifies that: Files remained unchanged Service health remained stable Configuration remained intact No unauthorized operation occurred If the target validation fails, Scope Guard performs a target-only rollback and verifies the environment again. This made rollback a controlled part of the execution transaction rather than an afterthought. Auditability Every significant workflow event is recorded in a chronological audit timeline. Examples include: Task received Inventory loaded Boundary proposed Boundary approved Snapshot created Action proposed Policy decision made Protected action blocked Corrected action received Approval granted Execution completed Health check failed Rollback started Previous state restored Protected resources verified The audit events are hash-chained, making accidental or unauthorized modifications to the event sequence detectable. Scope Guard also generates downloadable execution reports containing: Target resources changed Protected resources preserved Actions blocked Approvals required Validation results Rollback outcome Audit-chain status SentryBench I created a dedicated evaluation suite called SentryBench to test the policy engine beyond the main demonstration. It contains 32 scenarios across four categories: Safe in-scope operations Examples include editing RD Social files, running its tests, and restarting its approved service. Cross-project operations Examples include restarting EngageFlow, accessing its database, or modifying its environment variables. Destructive operations Examples include recursive deletion, unrelated database operations, secret access, and unsafe configuration changes. Ambiguous operations Examples include generic service names, unknown paths, shared resources, and attempted workspace escapes. The current evaluation result is: I also added regression tests to ensure the main guarded execution story continues to work as the policy system evolves. Challenges I Faced Building without weakening the security model The hardest design challenge was deciding where AI reasoning should stop and deterministic enforcement should begin. GPT-5.6 is excellent at understanding intent and explaining complex situations, but infrastructure permissions should not depend entirely on probabilistic output. The final architecture uses AI for interpretation and correction while preserving deterministic enforcement. Keeping the project generic while demonstrating a real story A completely generic infrastructure-security platform would have been too broad for the hackathon. A hard-coded demonstration would have been easier but less credible. I addressed this by using a concrete RD Social and EngageFlow scenario while designing the internal models around typed resources, actions, manifests, and decisions. Simulating realistic infrastructure safely I wanted the system to execute real operations, detect failures, and perform rollback, but I did not want the hackathon project to touch production systems. The Docker environment had to behave realistically enough to demonstrate the workflow while remaining disposable and isolated. WSL and Docker stability I built the project on a Windows PC using Ubuntu through WSL2. During development, Docker Desktop integration and browser automation occasionally destabilized the WSL session. This forced me to improve container cleanup, browser-test isolation, resource controls, and documentation around WSL recovery. Those interruptions were frustrating, but they reinforced one of the central lessons behind Scope Guard: powerful automation must operate within explicit resource boundaries. Designing a clear user experience Security tools often expose raw policy logs and expect the developer to interpret them. I wanted Scope Guard to explain: What the agent attempted What resource was affected Why it was blocked Which rule made the decision What the corrected action should be Making those decisions understandable was as important as implementing the underlying policy engine. What I Learned The most important lesson was that agent safety is not only about restricting access. An agent may have legitimate access to a workspace and still perform the wrong operation. The missing layer is task-specific authorization. I also learned that language models and deterministic systems are strongest when they are given different responsibilities: GPT-5.6 interprets intent and explains risk. Codex performs development work and revises plans. The policy engine enforces boundaries. The human approves sensitive operations. The sandbox limits the execution environment. Validation and rollback verify the outcome. No single layer is sufficient on its own. I also gained a deeper appreciation for evaluation. Building SentryBench forced me to define what “safe” actually meant in measurable terms rather than relying on an impressive demonstration alone. Accomplishments I Am Proud Of I am particularly proud that Scope Guard is not only a visual prototype. The project includes: A real deterministic policy engine A structured GPT-5.6 planning adapter A live Codex proposal integration Human approval gates A Docker-based synthetic shared-server environment Real blocked-action handling Failure injection Target-only rollback Protected-resource integrity verification Hash-chained audit events Downloadable reports A responsive six-route control plane Desktop and mobile browser verification 32 SentryBench scenarios Comprehensive backend and frontend testing The complete verification suite currently includes: Ruff passing Strict MyPy passing 30 backend tests passing Frontend tests passing ESLint passing TypeScript passing Next.js production build passing Docker Compose validation passing Playwright verification across all six routes Successful full signature scenario Successful rollback with EngageFlow remaining healthy and unchanged What Comes Next Scope Guard currently demonstrates the core safety loop in a controlled environment. The next stage is to expand it into a broader agent-safety platform with: Generic caller-defined resource manifests GitHub and CI/CD integrations Remote runner support Kubernetes resource boundaries Cloud deployment policies Organisation-level policy packs Durable audit storage Signed audit records Team-based approval workflows Fine-grained API keys and quotas Additional coding-agent integrations Policy simulation before execution Historical risk analytics I also see Scope Guard evolving into a standard safety layer that sits between coding agents and developer infrastructure. As agents become more capable, the important question will no longer be whether they can perform an operation. It will be whether that operation belongs to the task, respects the intended project boundary, and can be safely reversed. That is the problem Scope Guard is designed to solve. Let coding agents move fast without letting them wander.

## README (from the GitHub repository)

# Scope Guard

> **Let coding agents move fast—without letting them wander.**

Scope Guard, internally codenamed **Codex Sentry**, is an intent-bound execution control
plane for coding agents. It lets a structured planner interpret a task and propose a boundary,
while a deterministic policy engine stands between every proposed action and the isolated
execution runner.

Live demo: [scopeguard-vert.vercel.app](https://scopeguard-vert.vercel.app). It needs no
judge-supplied API credentials, is disconnected from production infrastructure, and uses a safe,
resettable synthetic environment. The complete writable Docker sandbox remains local by design.

![Scope Guard dashboard](docs/assets/dashboard.png)

## Judge quick start

- **Public demo:** [scopeguard-vert.vercel.app](https://scopeguard-vert.vercel.app)
- **Repository:** [github.com/gethsun1/scope-guard](https://github.com/gethsun1/scope-guard)
- **Safety profile:** no production infrastructure is connected. The hosted demo is deterministic,
  resettable, and requires no API key; the local version uses the complete writable Docker sandbox.

Fastest path through the deployed application:

1. Open **Guarded task** and use the seeded RD Social instruction.
2. Review and approve the proposed boundary.
3. Open **Execution** and start execution.
4. Inspect the blocked EngageFlow action.
5. Approve the corrected RD Social action.
6. Observe failure injection, target-only rollback, and protected-resource integrity.
7. Review or download the report.
8. Open **SentryBench** to inspect the generated policy results.

The public demo and local writable sandbox intentionally have different safety profiles. For the
real containerized runner, use the [complete local Docker instructions](#run-locally) and the
[local end-to-end verification notes](docs/LOCAL_END_TO_END_VERIFICATION.md).

## The problem

Shared development environments make scope drift dangerous: an agent can successfully
deploy the requested service while also restarting a neighbor, reading an unrelated secret,
or migrating the wrong database. A normal sandbox answers what is technically reachable.
Scope Guard also asks whether the action belongs to the approved task and project.

## Thirty-second explanation

1. A structured planner interprets natural-language intent and proposes a typed boundary. Live
   mode uses GPT-5.6; the public sandbox uses a clearly labeled deterministic provider with the
   same validated schema.
2. A person approves the target, protected resources, validation plan, and rollback plan.
3. Codex proposes actions, and a deterministic engine parses and evaluates every proposed operation.
4. Allowed actions run through the isolated predefined-operation runner; protected actions are
   blocked before execution.
5. Target health checks, protected-resource integrity, rollback, and a hash-chained audit report
   provide evidence of the result.

## Signature scenario

> Update and deploy RD Social, run its approved migration, restart its API, and verify its
> health without modifying EngageFlow.

The deterministic demo Codex adapter first edits RD Social, then mistakenly proposes
`systemctl restart engageflow-api`. Scope Guard returns `BLOCK_PROTECTED_RESOURCE` and a
structured correction. The corrected RD Social restart requires approval. Failure injection
then makes RD Social unhealthy, triggers target-only rollback, and proves EngageFlow retained
the same hash and health state.

## Features

- Typed project inventory and resource graph
- GPT-5.6 Responses API adapter plus clearly labeled offline demo planner
- Read-only Codex app-server proposal adapter plus deterministic `codex_demo` event provider
- Structured command parsing, normalized paths, and deterministic deny-by-default policy
- Explicit boundary and medium/high-risk action approvals
- Non-root Docker runner with no socket, host-root, privileges, secrets, or external network
- Snapshots, target validation, protected-resource verification, and task-scoped rollback
- SSE audit timeline and downloadable JSON/Markdown execution reports
- 32-scenario SentryBench with generated metrics
- Responsive DevOps control-plane interface—not a chat wrapper

## Architecture

```mermaid
flowchart LR
  U[Developer] --> W[Next.js control plane]
  W --> A[FastAPI orchestrator]
  A --> P[Planner: GPT-5.6 live or deterministic demo]
  A --> C[Codex adapter]
  C --> E[Deterministic policy engine]
  E -->|allow / approval| R[Predefined Docker runner]
  E -->|block + context| C
  R --> RD[RD Social target]
  R -. integrity only .-> EF[EngageFlow protected]
  A --> AU[Hash-chained audit]
```

This diagram represents the complete local execution topology. The hosted demo replaces the
writable Docker runner with a synthetic in-memory state machine that has no shell or Docker access.

Details: [architecture](docs/ARCHITECTURE.md) and [threat model](docs/THREAT_MODEL.md).

### Responsibility split

**GPT-5.6** interprets intent, proposes a typed boundary, explains risk, and drafts validation and
rollback plans. Its strict JSON is validated, but it never grants authority.

**Codex** accelerated implementation and can propose development actions, receive structured
policy rejection, revise an action, and continue the guarded workflow. `codex_demo` is the
reproducible deterministic event provider. `codex_live` is the read-only app-server adapter; its
manual smoke test verified startup, schema validation, four typed proposals, and thread capture.
That smoke was proposal-only: it did not run the Docker workflow or execute a corrected action set.

**The deterministic policy engine** is final authority. It parses actions, extracts resources,
matches the approved manifest, denies unknown resources, detects destructive and protected
operations, and determines allow, approval, or block outcomes. It overrides any conflicting model
recommendation.

## How I used Codex and GPT-5.6

### Codex

I built Scope Guard primarily through one Codex IDE session. Codex accelerated the monorepo
scaffolding; FastAPI and Next.js implementation; typed domain models; command parsing and
deterministic policy enforcement; Docker fixtures; block, correction, approval, validation, and
rollback workflows; audit and reporting; frontend work; backend and frontend tests; Playwright
verification; SentryBench; WSL and Docker troubleshooting; deployment preparation; and the final
documentation and submission evidence.

I reviewed the output and retained responsibility for the product and trust-boundary decisions.
The Codex `/feedback` session ID is supplied privately in the Devpost form and is intentionally not
published in this repository.

### GPT-5.6

Scope Guard implements a GPT-5.6 Responses API planner adapter. It converts a natural-language
task, infrastructure inventory, resource relationships, constraints, and supported operations into
schema-validated structured output containing:

- interpreted intent and target project
- allowed and protected resources
- proposed actions and a risk summary
- validation and rollback plans
- confidence and open questions

GPT-5.6 does not authorize actions. Malformed output fails schema validation, model output cannot
silently expand an approved manifest, and the deterministic policy engine has final authority. The
public demo uses a deterministic planner that implements the same validated schema.

The repository records GPT-5.6 as the implemented live planner, but it does not independently record
the underlying model configuration of the primary Codex development session. I therefore do not
claim here that GPT-5.6 powered that session.

### Decisions I retained as the developer

I chose to focus on semantic scope drift rather than generic shell access. I kept model reasoning
outside the enforcement boundary, gave deterministic policy final authority, denied unknown
resources by default, and required approval for medium- and high-risk mutations. I also chose
synthetic infrastructure, independent 

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 64 recognized source files, 359 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- TypeScript (language) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (92 of 92)

```
.dockerignore
.env.example
.github/workflows/ci.yml
.gitignore
.npmrc
AGENTS.md
apps/api/Dockerfile
apps/api/scope_guard/__init__.py
apps/api/scope_guard/audit.py
apps/api/scope_guard/codex.py
apps/api/scope_guard/command_parser.py
apps/api/scope_guard/config.py
apps/api/scope_guard/engine.py
apps/api/scope_guard/inventory.py
apps/api/scope_guard/main.py
apps/api/scope_guard/models.py
apps/api/scope_guard/planner.py
apps/api/scope_guard/policy.py
apps/api/scope_guard/smoke.py
apps/api/tests/test_codex_adapter.py
apps/api/tests/test_hosted_runner.py
apps/api/tests/test_models_planner.py
apps/api/tests/test_policy.py
apps/api/tests/test_signature_flow.py
apps/web/.gitignore
apps/web/app/execution/page.tsx
apps/web/app/globals.css
apps/web/app/inventory/page.tsx
apps/web/app/layout.tsx
apps/web/app/page.tsx
apps/web/app/report/page.tsx
apps/web/app/sentrybench/page.tsx
apps/web/app/tasks/new/page.tsx
apps/web/components/control-plane.test.tsx
apps/web/components/control-plane.tsx
apps/web/Dockerfile
apps/web/e2e/submission.spec.ts
apps/web/eslint.config.mjs
apps/web/lib/api.ts
apps/web/next-env.d.ts
apps/web/next.config.ts
apps/web/package.json
apps/web/playwright.config.ts
apps/web/tsconfig.json
apps/web/vercel.json
apps/web/vitest.config.ts
apps/web/vitest.setup.ts
demo/configs/engageflow.baseline.json
demo/configs/inventory.json
demo/configs/rdsocial.baseline.json
demo/docker-compose.demo.yml
demo/projects/engageflow/app.py
demo/projects/engageflow/Dockerfile
demo/projects/engageflow/project.json
demo/projects/rdsocial/app.py
demo/projects/rdsocial/Dockerfile
demo/projects/rdsocial/project.json
demo/scripts/Dockerfile
demo/scripts/Dockerfile.init
demo/scripts/runner.py
docker-compose.yml
docs/ARCHITECTURE.md
docs/CODEX_COLLABORATION.md
docs/DEMO_SCRIPT.md
docs/DEPENDENCY_SECURITY_REVIEW.md
docs/DEPLOYMENT.md
docs/DEVPOST_SUBMISSION.md
docs/EVALUATION.md
docs/FINAL_GAP_ANALYSIS.md
docs/FINAL_READINESS.md
docs/LIVE_PROVIDER_VERIFICATION.md
docs/LOCAL_END_TO_END_VERIFICATION.md
docs/PRODUCT_DECISIONS.md
docs/SUBMISSION_EVIDENCE.md
docs/THREAT_MODEL.md
docs/VIDEO_RECORDING_CHECKLIST.md
docs/WSL_STABILITY.md
evaluations/sentrybench/results/latest-dashboard.json
evaluations/sentrybench/results/latest.json
evaluations/sentrybench/results/latest.md
evaluations/sentrybench/run.py
LICENSE
Makefile
package.json
pnpm-workspace.yaml
pyproject.toml
railway.json
README.md
scripts/verify-clean-clone.sh
scripts/verify-hosted-demo.sh
uv.lock
vercel.json
```

### Dependencies

- apps/web/package.json: @eslint/eslintrc@^3.3.1, @next/eslint-plugin-next@^15.5.20, @playwright/test@^1.61.1, @tanstack/react-query@^5.83.0, @testing-library/jest-dom@^6.6.3, @testing-library/react@^16.3.0, @types/node@^24.0.13, @types/react@^19.1.8, @types/react-dom@^19.1.6, eslint@^9.31.0, eslint-config-next@^15.4.1, eslint-plugin-react@^7.37.5, eslint-plugin-react-hooks@^7.1.1, jsdom@^26.1.0, lucide-react@^0.525.0, next@^15.4.1, react@^19.1.0, react-dom@^19.1.0, recharts@^3.1.0, typescript@^5.8.3, vitest@^3.2.4, zod@^4.0.5
- pyproject.toml: aiosqlite@>=0.21,<1, fastapi@>=0.116,<1, httpx@>=0.28,<1, openai@>=1.90,<2, pydantic-settings@>=2.10,<3, sqlalchemy@>=2.0,<3, uvicorn[standard]@>=0.35,<1

### Recent commits (newest first)

- docs: strengthen build week README for judging
- docs: finalize build week submission evidence
- test: add clean clone and hosted verification scripts
- fix: address submission dependency security findings
- Added Codex Feedback session ID docs
- feat: deploy hosted scope guard demo
- docs: prepare scope guard hackathon submission
- test: verify guarded execution end to end
- feat: complete live provider integration
- fix: preserve guarded task across control plane routes
- chore: finalize scope guard readiness
- feat: complete execution dashboard
- test: add sentrybench evaluation suite
- feat: integrate codex guarded execution flow
- feat: add synthetic shared-server environment
- feat: scaffold control plane monorepo
- chore: initialize scope guard workspace

## Key source files (fetched from GitHub, selected and truncated for size)

### AGENTS.md

```markdown
# Scope Guard contributor guide

Operate only inside this repository. Never inspect or mutate real services, databases,
Docker resources, reverse proxies, SSH state, or other projects. The names RD Social and
EngageFlow refer exclusively to fixtures under `demo/`.

Security decisions must remain deterministic. Model adapters may propose or explain, but
must never override policy. Unknown resources are denied. Never log secrets. Run the
relevant tests after changes and preserve the protected-project integrity invariants.


```

### docs/DEPENDENCY_SECURITY_REVIEW.md

```markdown
# Dependency security review

Reviewed JavaScript and Python manifests and lockfiles on 2026-07-16.

`pnpm audit` identified moderate advisory `GHSA-qx2v-qp2m-jg93`: Next.js resolved PostCSS
`8.4.31`, whose CSS stringifier could emit an unescaped closing style tag. The root pnpm override
now requires PostCSS `>=8.5.10 <9`, the advisory's patched range, without changing framework
majors. The lockfile was regenerated normally.

The earlier GitHub UI reportedly showed two moderate alerts. Only the PostCSS advisory is
reproducible from the current lockfile; no second vulnerable dependency is reported locally.
Live GitHub Dependabot state requires repository-alert access and must not be inferred from an old
badge or deployment log. Python dependencies have no repository-native audit tool configured.

Verification includes Ruff, MyPy, Pytest, Vitest, ESLint, TypeScript, production build, and a
fresh `pnpm audit`. No forced major-version fix was used.

```

### package.json

```
{"name":"scope-guard","private":true,"packageManager":"pnpm@11.13.0","scripts":{"dev":"pnpm --filter web dev","build":"pnpm --filter web build","lint":"pnpm --filter web lint","typecheck":"pnpm --filter web typecheck","test":"pnpm --filter web test"}}

```

### pyproject.toml

```
[project]
name = "scope-guard"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["fastapi>=0.116,<1", "uvicorn[standard]>=0.35,<1", "pydantic-settings>=2.10,<3", "sqlalchemy>=2.0,<3", "aiosqlite>=0.21,<1", "httpx>=0.28,<1", "openai>=1.90,<2"]

[dependency-groups]
dev = ["pytest>=8.4,<9", "pytest-asyncio>=1.0,<2", "ruff>=0.12,<1", "mypy>=1.16,<2"]

[tool.uv]
package = false

[tool.ruff]
line-length = 120
target-version = "py311"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]

[tool.pytest.ini_options]
pythonpath = ["apps/api"]
testpaths = ["apps/api/tests"]
asyncio_mode = "auto"

[tool.mypy]
python_version = "3.11"
strict = true
files = ["apps/api/scope_guard"]

```

### docker-compose.yml

```yaml
name: scope-guard
services:
  api:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
    environment:
      DEMO_MODE: "true"
      DATABASE_URL: sqlite+aiosqlite:////data/scopeguard.db
      ALLOWED_ORIGINS: http://localhost:3000
      DEMO_WORKSPACE_ROOT: /workspace
    ports: ["8000:8000"]
    volumes:
      - scopeguard-data:/data
      - demo-workspace:/workspace
    read_only: true
    tmpfs: [/tmp]
    security_opt: [no-new-privileges:true]
    cap_drop: [ALL]
    mem_limit: 512m
    cpus: 1.0
    healthcheck:
      test: [CMD, python, -c, "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
      interval: 10s
      timeout: 3s
      retries: 5
  web:
    build:
      context: .
      dockerfile: apps/web/Dockerfile
    environment:
      NEXT_PUBLIC_API_URL: http://localhost:8000
      HOSTNAME: 0.0.0.0
    ports: ["3000:3000"]
    depends_on:
      api: {condition: service_healthy}
    read_only: true
    tmpfs: [/tmp]
    security_opt: [no-new-privileges:true]
    cap_drop: [ALL]
    mem_limit: 512m
    cpus: 1.0
    healthcheck:
      test: [CMD, wget, -qO-, http://127.0.0.1:3000]
      interval: 10s
      timeout: 3s
      retries: 5
volumes:
  scopeguard-data:
  demo-workspace:

```

### demo/scripts/Dockerfile

```
FROM python:3.12-alpine
RUN addgroup -S demo && adduser -S -G demo -u 10001 demo
WORKDIR /runner
COPY demo/scripts/runner.py .
USER 10001:10001
EXPOSE 9000
CMD ["python", "runner.py"]


```

### apps/api/Dockerfile

```
FROM python:3.12-slim
RUN groupadd -r scopeguard && useradd -r -g scopeguard -u 10001 scopeguard
WORKDIR /app
COPY pyproject.toml uv.lock* ./
RUN pip install --no-cache-dir uv && uv sync --frozen --no-dev
COPY apps/api ./apps/api
USER 10001:10001
ENV PATH="/app/.venv/bin:$PATH" PYTHONPATH=/app/apps/api
EXPOSE 8000
CMD ["uvicorn", "scope_guard.main:app", "--host", "0.0.0.0", "--port", "8000"]

```

### apps/web/Dockerfile

```
FROM node:24-alpine AS build
RUN corepack enable
WORKDIR /app
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml* ./
COPY apps/web/package.json apps/web/package.json
RUN pnpm install --frozen-lockfile
COPY apps/web apps/web
RUN pnpm --filter web build
FROM node:24-alpine
RUN addgroup -S scopeguard && adduser -S -G scopeguard -u 10001 scopeguard
WORKDIR /app
COPY --from=build --chown=scopeguard:scopeguard /app/apps/web/.next/standalone ./
COPY --from=build --chown=scopeguard:scopeguard /app/apps/web/.next/static ./apps/web/.next/static
USER scopeguard
EXPOSE 3000
CMD ["node", "apps/web/server.js"]


```

### apps/web/package.json

```
{"name":"web","private":true,"version":"0.1.0","scripts":{"dev":"next dev","build":"next build","start":"next start","lint":"eslint .","typecheck":"tsc --noEmit","test":"vitest run","test:e2e":"playwright test"},"dependencies":{"@tanstack/react-query":"^5.83.0","lucide-react":"^0.525.0","next":"^15.4.1","react":"^19.1.0","react-dom":"^19.1.0","recharts":"^3.1.0","zod":"^4.0.5"},"devDependencies":{"@eslint/eslintrc":"^3.3.1","@next/eslint-plugin-next":"^15.5.20","@playwright/test":"^1.61.1","@testing-library/jest-dom":"^6.6.3","@testing-library/react":"^16.3.0","@types/node":"^24.0.13","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","eslint":"^9.31.0","eslint-config-next":"^15.4.1","eslint-plugin-react":"^7.37.5","eslint-plugin-react-hooks":"^7.1.1","jsdom":"^26.1.0","typescript":"^5.8.3","vitest":"^3.2.4"}}

```

### demo/projects/rdsocial/Dockerfile

```
FROM python:3.12-alpine
RUN addgroup -S demo && adduser -S -G demo -u 10001 demo
WORKDIR /app
COPY demo/projects/rdsocial/app.py .
USER 10001:10001
EXPOSE 8101
CMD ["python", "app.py"]


```

[60 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]