Aller au contenu principal

App Works — threat model

Status: Draft · Created: 2026-09-17 · Program: App Works · Closes: SK-06 and XC-03 (one document discharges both audit rows — a single programme-level threat model) Companion: the platform-wide Ever Works threat model — §1 of that document states the general agent-CLI posture; this document states what this programme adds to it. Audience: Engineering (backend, platform/infra, security review), Product.

This file is the one place that maps what the programme runs to what stops it going wrong and to the acceptance scenario that proves the control. Every control cites a real file:line in this tree or in this repository, every verification id is defined in ACCEPTANCE.md, and every resolution id (R-n) refers to CONTRACTS.md §0.

Public-repository hygiene (README §7 rule 10, README.md:373-376). This repository is public. Nothing below names an internal infrastructure address, a hostname of an internal system, an unpatched weakness with a reproduction, or an undisclosed third-party vulnerability. Where a control's implementation is sensitive — zone network design, credential scopes, audit evidence — this document records the requirement and its evidence location and points at the private operations repository (§5). Known-but-unfixed platform weaknesses are described generically, per R-14 (CONTRACTS.md:57).

Additive-only (R-26, CONTRACTS.md:69). Nothing here narrows an existing control, marks existing behaviour "not applicable", or removes a deploy shape. Every boundary below already appears somewhere in the epics; this document collects them, it does not re-scope them.


0. How to read this document​

id shapemeaning
B-na trust boundary — one edge where data or authority crosses from a less-trusted to a more-trusted side
T-nnone threat on that boundary, classified with STRIDE
R-na binding programme resolution in CONTRACTS.md §0
LG-nna launch-gate item in APW-10-apps-hosting-tier/spec.md:181-207
ACC-…an acceptance scenario (or negative scenario ACC-NEG-…, or end-to-end ACC-E2E-…) in ACCEPTANCE.md

STRIDE letters used in the tables: Spoofing · Tampering · Repudiation · Information disclosure · Denial of service · Elevation of privilege.

Three conventions worth stating once:

  1. The wave in which a residual risk is accepted refers to the programme waves in README.md:302-307. A control that ships in a later phase (e.g. sandboxed in-zone builds, R-24 at CONTRACTS.md:67) is recorded as residual until then — never as "not applicable".
  2. A refusal is a control. Several rows below are verified by the platform declining to start (no sandbox → no provisioning run, APW-04-app-provisioner/spec.md:215-216; no Fleet node and no isolated environment → no run, APW-08-evolve-loop/spec.md:236-238). Those are counted as controls, and their acceptance ids are negative scenarios.
  3. Blast-radius ownership. Wave 1 runs user code only where the user owns the consequences — their cluster, their GitHub Actions minutes (README.md:309-310). Several accepted residuals rest on that, and the table says so explicitly rather than implying platform-side isolation that does not exist yet.
  4. This file is the register Resolution R-37 requires (CONTRACTS.md:80): the threat → control → owning epic → verifying acceptance mapping lives here, and CONTRACTS.md §10 indexes the boundaries. Threat ids are stable, never re-sequenced: T-34 sits inside B-2's table and T-35 inside B-12 because they were added after the first pass, and an id that has been cited is not renumbered (R-26).

1. Assets​

AssetWhere it livesWhy it mattersContract / owner
The user's application code, and its historyThe Work Repository (persisted role website, README.md:81-100) — a fork, a private copy or a linkIt is the user's product; the platform may change it only through branches and pull requestsREADME.md:128-132 (D3), APW-08-evolve-loop/spec.md:222-232
The fork / private copy's relationship to upstreamWorkUpstreamState, work_upstream_statesContinuity of the fork network; losing it breaks sync and blocks contributing backCONTRACTS.md:252, APW-02-fork-lifecycle/spec.md:325-326
App env values and secrets (generated, prompted, derived)work_app_env_values, encrypted; rendered into a cluster Secret or an Actions secretThey are the app's own keys — a leak is a breach of the user's app, and reuse across apps is worseREADME.md:191-197 (D9), APW-07-app-env-and-dependencies/spec.md:204-208
Git connections and tokens (member OAuth, PAT, installation tokens, per-App-Work pull tokens)Plugin settings, encrypted; resolved per call by resolvePluginAndTokenThey carry write authority over the user's repositories and, if broad, over an organizationEXISTING-SUBSTRATE.md:73, APW-05-builds/spec.md:326-329
User-supplied kubeconfigsStored encrypted per App Work, never returned by any endpointThey are cluster-admin-equivalent credentials to infrastructure the platform does not ownAPW-06-app-runtime/spec.md:252-255
Tenant workloads and tenant data (databases, buckets, volumes)On the user's cluster or on Ever Works Apps; one namespace per App WorkCo-tenancy is the platform's reputation; a cross-tenant reach is a platform-level incidentAPW-10-apps-hosting-tier/spec.md:264-273, README.md:258-268 (D15)
Platform credentials (platform PAT, installation-wide credentials, control-namespace credential, DNS token)Server-side only; never handed to a tenant or a sandboxThey reach every customer the platform servesAPW-10-apps-hosting-tier/spec.md:276-278 (FR-23), CONTRACTS.md:433
The platform's own agent-run capacity (tokens, runner minutes)Receipts and capsPrompt-injected agents spend the owner's money; unbounded spend is a denial of serviceREADME.md:379-380 (rule 12), CONTRACTS.md:426-427
The user's reputation upstreamTheir GitHub identity and the pull requests opened in their nameAn unwanted or low-quality contribution damages a person's standing in a project they care aboutAPW-09-upstream-pull-requests/spec.md:240-245 (FR-21), README.md:236-239 (D12)
The runtime catalogs (ever-works/templates, ever-works/platforms, Blueprint repositories)Outside this monorepo; read at runtimeThey steer what gets built, deployed, hosted and shown — an executable supply chainCONTRACTS.md:440-451, README.md:134-160 (D4)
Activity, telemetry and build logsPlatform database; log excerpts are transientThey are the audit trail and a classic accidental-secret channelREADME.md:367-368 (rule 8), APW-06-app-runtime/spec.md:492

2. Actors​

ActorCapability the programme must assumePrimary assets at riskGrounded in
Malicious upstream authorOwns the repository the user pointed at: writes the README, AGENTS.md, CONTRIBUTING.md, workflow files, the pre-seeded App spec and the build stepsAgents' instructions, the App spec, the build, the user's CI, reputationAPW-13-golden-paths/spec.md:212-224, APW-04-app-provisioner/spec.md:254-256
Malicious or compromised App Work owner (tenant)Owns an App Work: controls its fork, its App spec, its checks, its kubeconfig target and its app code; asks agents to change thingsCo-tenants (on the managed tier), the platform's own clusters, the platform's credentialsREADME.md:258-268 (D15), APW-10-apps-hosting-tier/spec.md:267-273
Co-tenantRuns their own App Work on shared infrastructure and tries to reach another tenant, the zone control plane, or the platformTenant data, the managed tier, the platform's reputationAPW-10-apps-hosting-tier/spec.md:184-196 (LG-02…LG-14)
Compromised catalog contributorCan land a row or a file in the runtime catalogs (a poisoned image reference, a hostile Blueprint, a malicious platform URL)Every App Work that resolves through the catalog, launcher tilesREADME.md:134-160 (D4), APW-03-app-spec-and-catalog/plan.md:213-216
Abusive contributor (the user, or their agents)Can ask for upstream pull requests at machine speed; can host content on the managed tierUpstream maintainers' attention; the tier's egress reputation (mail, mining)APW-09-upstream-pull-requests/spec.md:262-267, APW-10-apps-hosting-tier/spec.md:201-202
External attacker against user-app domainsReaches a deployed App Work over the public internet; a hosted app is an internet-facing service the platform publishedThe app's own data; the tier's network; the platform's shared edgeAPW-10-apps-hosting-tier/spec.md:188-199, APW-06-app-runtime/spec.md:327-330
Anonymous internet visitorReads the public catalogs (GET /api/apps-catalog, GET /api/app-launcher/platforms) with no accountCatalog integrity (read-only surface)CONTRACTS.md:334, CONTRACTS.md:350
A delegated third-party originHolds a read-only Ever ID token for a person and can call the marked read route from a browserThe person's App Work list (names and addresses)APW-11-app-launcher/spec.md:305-308, CONTRACTS.md:62 (R-19)

The platform-wide actor table (anonymous visitor, registered tenant, malicious tenant, compromised plugin author, compromised CI, cluster peer) stays valid and is not repeated here — see the sibling document §3.


3. Trust boundaries​

IdBoundaryDirectionTrust
B-1A user's / upstream's repository → the App Provisioner agent and the evolve agentsinbound (untrusted content)Untrusted input. Every byte is treated as hostile: instructions in it can shape format and scope, never authority (README.md:369-372; APW-04-app-provisioner/spec.md:254-256)
B-2App spec checks and repository-authored commands → Fleet nodes, the user's CI, verification runnersoutbound executionExecuted untrusted code, by design, only where the owner holds the blast radius (APW-08-evolve-loop/spec.md:236-246)
B-3The platform-written workflow → GitHub Actions in the user's repository (with EW_ secrets), and the workflow's artifact back to the platformboth waysHalf-trusted both ways. The file is platform-generated but the repository can edit it; the artifact is untrusted until the digest is confirmed against the registry (CONTRACTS.md:462)
B-4A user-supplied kubeconfig → the cluster-op worker dialling the user's clusteroutboundUntrusted credential, guarded before any connection (APW-06-app-runtime/spec.md:252-259, APW-06-app-runtime/plan.md:871-888)
B-5Tenant workloads on Ever Works Apps → the zone, other tenants and the platforminbound (untrusted workload)Untrusted workload in an isolated zone, admitted only while the launch gate is green (APW-10-apps-hosting-tier/spec.md:176-215)
B-6Runtime-loaded catalogs (ever-works/templates, ever-works/platforms, Blueprint repositories) → builds, deploys and the launcherinbound (supply chain)Curated, but a supply chain: rows are validated and sanitized, licences gate hosting, verification is explicit (APW-03-app-spec-and-catalog/spec.md:255-260)
B-7Delegated Ever ID tokens + cross-origin launcher reads → GET /api/me/appsinboundNarrowly admitted: read-only scope, marked routes only, exact-origin allow-list (CONTRACTS.md:317, APW-11-app-launcher/spec.md:305-308)
B-8The non-production EVER_WORKS_E2E_FAKES switch → the Git provider base URLlocal (test-only redirect)Test harness only, non-production only (CONTRACTS.md:437, ACCEPTANCE.md:80)
B-9Upstream repositories ← pull requests sent in the member's nameoutbound in the member's identityThe member's own token and the member's own decision — never a platform or installation token (APW-09-upstream-pull-requests/spec.md:252-256)
B-10User-supplied external endpoints (S3, SMTP, webhook receiver, the app's own public URL) → platform HTTP clientsoutboundSSRF-guarded: public hostnames only, no redirects followed, validated before any connection (APW-07-app-env-and-dependencies/plan.md:569-570)
B-11Platform credentials and tenant data at rest → any read surface (API, logs, Activity, backup export)localEncrypted, never returned, redacted in every text that leaves a run (README.md:367-368; CONTRACTS.md:68, R-25)

The boundaries the platform already had — public internet → the API, MCP, the trigger worker, the agent subprocess, Postgres, the agent workspace, community PRs, plugins on disk — are unchanged and are documented once in the sibling §2. App Works adds the eleven above.


4. Threat register by boundary​

B-1 — Untrusted repository content → the App Provisioner and the evolve agents​

What crosses. The Provisioner reads a repository nobody has vetted: READMEs, AGENTS.md, CONTRIBUTING.md, code comments, compose files, Dockerfiles, workflow files, installer scripts and a possibly pre-seeded .works/works.yml. The evolve loop reads the same content on every Task. The sibling document's §1 states the platform-wide risk in one line: the agentic CLI runs with the API process's permissions rather than a sandbox, so prompt injection inside the agent loop is equivalent to remote code execution on the API host (../../security/THREAT-MODEL.md). This programme's answer is to not put such a run in that position — see §6.

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-01EInjected instructions make the agent act with platform reach (call tools, push, open PRs, exfiltrate)README §7 rule 9 (README.md:369-372); the provisioning Agent's tool list is limited to sandbox read/write, progress, draft validation and asking (APW-04-app-provisioner/spec.md:209-211); committing and PR-opening are the platform's own Task-finalize step, outside the sandbox (APW-04-app-provisioner/plan.md:677-680)ACC-04-34, ACC-NEG-05, ACC-E2E-06Accepted in Wave 1. The fence is the tool list plus the sandbox — not the model's judgement — so an injection that "wins" the conversation still has nothing to call.
T-02IThe injected instruction asks for env values, a kubeconfig, a token or an Actions secretThe sandbox receives repository contents and nothing else (APW-04-app-provisioner/spec.md:220-221); reach is exactly the repository host, public package/container registries (:217-219); every text leaving the run is scanned and redacted (APW-04-app-provisioner/plan.md:667-676); the honeytoken/canary fixture proves it (APW-13-golden-paths/spec.md:219-224)ACC-04-06, ACC-04-34, ACC-NEG-05, ACC-13-04Accepted in Wave 1. Residual: content the user themselves typed into their own app is out of scope — the boundary is the repository, and the owner may always publish their own secrets.
T-03TThe agent writes outside its remit or weakens the spec (approval off, checks removed, licence misreported)Only .works/works.yml and .works/overlay/** are writable (APW-04-app-provisioner/spec.md:262); a proposal is capped at 12 files / 3,000 lines / 128 KB each (:265); platform-owned spec fields are preserved (:266) and re-checked by a pure guard (APW-04-app-provisioner/plan.md:667-676); on the evolve side, protected paths, .github/workflows/** and source/license/blueprint changes open no pull request (APW-08-evolve-loop/spec.md:263-269)ACC-04-07, ACC-04-09, ACC-08-11, ACC-08-12, ACC-NEG-05Accepted in Wave 1. Residual: a human owner may of course weaken their own spec — the control constrains agents, and says so.
T-04S/RA change is attributed to the member that the member never approvedThe agent may not merge its own pull request (APW-04-app-provisioner/spec.md:208); commits and PRs go through Task finalize with the Task's actor (APW-04-app-provisioner/plan.md:677-683); every App Works agent run passes the run-admission chain (CONTRACTS.md:60, R-17)ACC-04-37, ACC-04-35, ACC-04-36, ACC-08-31Accepted in Wave 1. Residual: an approval the owner gives while a hostile repository is open in chat is still the owner's decision; prompt fencing reduces, never eliminates, that.

T-03, where the evolve-side control runs (updated 2026-09-25, APW-08 T17, 86e1a3ddf; 2026-09-26, cab3419e5, 08c05ee78).

  • The cloud Task finalize is judged before the push, and is off by default. The isolated-Task finalize (TaskWorkspaceService.finalizeRun) of a cloud (API-side) run on an App Work commits locally and pushes nothing until APW-08 T12's isolated-run admission lands; the Task is blocked with a message naming FR-12. With APP_WORKS_CLOUD_PUSH_ENABLED=true the exact local commit is judged (AppWorkChangeGate.checkPaths over IWorkspacePlugin.branchChanges, objects read literally — no replace refs, grafts, commit-graph or submodule ignore settings) and only that sha is published (publishSha) (APW-08/plan.md §2.5). finalizeRun and the agent git tools are its only callers, through one gate (appWorkCloudPushAllowed, packages/agent/src/tasks-domain/app-work-cloud-push.ts).
  • The agent git tools are behind the same switch (2026-09-26, cab3419e5). commitToRepo / openPullRequest run only in the API process (AGENT_GIT_FACADE, apps/api/src/agents/agents.module.ts:839) and ask finalizeRun's gate first. Off (the default until T12), an App Work call is refused with the FR-12 / T12 message, and nothing is written, committed, pushed or opened. On, commitToRepo refuses the Work's base branch, judges the call's own files and new content with AppWorkChangeGate.checkPaths before it writes, and pushes refs/heads/<branch> (:1395), which carries any commit already on the local branch; commits planted there by a shell on the API host are not judged again (T12). openPullRequest pushes nothing and runs AppWorkChangeGate.evaluate on the verified head before it opens (:1549). Both are offered to an Agent holding canCommitToRepo / canOpenPullRequests (packages/agent/src/agents/agent-tool.service.ts:355, :364), refuse at invoke time unless the Agent is Work-scoped, and pass the safety gate as publish.external (packages/agent/src/safety/action-category.ts:105). The evolve loop never depends on them (R-17). A model with a shell in a cloud workspace whose host carries an ambient git credential could still push outside every platform path; that is T12 containment, not this switch.
  • Website-template sync never targets an App Work (2026-09-26, 08c05ee78). An App Work's website role is its Work Repository. With the platform credential, the template pipelines force-push a template into it, force-sync every template branch and re-point the default branch; initialize also deletes the other branches. None of this passes through the change gate, the protected-branch floor or the switch. Both funnels, WebsiteUpdateService.updateRepository and WebsiteGeneratorService.initialize, now refuse the kind through assertNotAppWorkTemplateTarget (packages/agent/src/works/repository-work-guard.ts) before any provider or git call, and the hourly auto-update poller skips App Works. Before this, update_website (MCP, including a Fleet node's run token) and switch-website-template reached it.
  • Fleet runs still push before the platform judges. The platform's finalizeRemotePush and the merge gate judge the pushed branch afterwards, so protected non-workflow paths and guarded spec blocks can reach the Task branch before judgement; they execute nothing, and the merge gate re-judges the head. Workflow files are kept out by the push credential itself (contents: write only — GITHUB-PERMISSIONS.md §1), which is pinned in a spec but not yet verified live against GitHub. A model with shell access on a node whose ambient git credential helper can write could push during the run; that is node containment (APW-08 T48, FR-12, T-34).
  • Residual — merge-base judgement. Both judgements use merge-base semantics, the pull request's view. A head cut from an old ancestor of the base is judged only by what it changed since that ancestor, so a workflow file the ancestor carried and the base later removed can be published unnamed, and an on: push trigger in it runs on the push. Accepted for now and recorded in APW-08 T17; closing it needs a history-free comparison of the protected paths against a trusted remote task-branch tip.
  • The refusal is visible on the primary branch. A refused change that reached the remote is recorded on tasks.branchGuardRefusal and shown as a banner in the Task's branch panel (ACC-NEG-04).

B-2 — App spec checks and upstream code executed on Fleet nodes, in the user's CI, and on verification runners​

What crosses. spec.checks[].command is repository-authored text that the platform executes, and a Build runs the repository's own Dockerfile and build steps. The programme's rule is that this execution happens only where the owner holds the blast radius, and never on shared platform machines outside an isolation boundary.

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-05EA repository-authored check runs on a shared platform machine with platform reachREADME §7 rule 9 — checks run sandboxed, and nothing from a repository is executed on platform infrastructure outside a sandbox (README.md:371-372); checks execute only on the Fleet node running the Task or in the App Work's own repository CI, with a read-only token and no secrets (APW-08-evolve-loop/spec.md:239-242); on a Fleet node each command must have been admitted by the owner for their machines (:243-246)ACC-08-08, ACC-08-10, ACC-04-05, ACC-05-29, ACC-NEG-05Accepted in Wave 1. Residual: a Fleet node is the owner's machine, so a hostile check there is the owner's own blast radius — by design, and the gated item is located per shape rather than waived (R-27, CONTRACTS.md:70).
T-06IA check or a Build step exfiltrates a secret it can seeThe build workflow requests only contents: read + packages: write (APW-05-builds/spec.md:233-234); the checks job carries permissions: contents: read and no secrets. or EW_ reference at all (CONTRACTS.md:314, APW-05-builds/plan.md:872-876); check commands travel base64-encoded so neither YAML nor the expression engine interprets repository text (APW-05-builds/spec.md:377-379); upstream-documented checks run in the same isolated environment with no secrets or credentials (APW-09-upstream-pull-requests/spec.md:208-212)ACC-05-29, ACC-05-06, ACC-09-06, ACC-NEG-05, ACC-E2E-06Accepted in Wave 1. Residual: a build step can always exfiltrate what the build legitimately receives (its own build-time values); that is why the secret-in-image check exists (T-08) and why build-phase values are minimised (README.md:191-197).
T-07DA hostile or merely heavy check/Build burns the owner's minutes or the platform's token budgetCheck timeouts 1–3,600 s and at most 20 checks (APW-08-evolve-loop/spec.md:257-259); build timeoutMinutes in the spec and a hard deployment limit (APW-05-builds/plan.md:174, APW-06-app-runtime/spec.md:366); analysis runs 45 min / iterate 30 min and repositories over 3 GiB fail fast (APW-04-app-provisioner/spec.md:222-223); per-provisioning token and runner-minute caps (CONTRACTS.md:426-427); every unbounded action also carries a documented per-member and per-organization cap with a refusal code and copy, and a cap refusal never deletes (CONTRACTS.md:74, R-31); every spend produces a receipt (README.md:379-380)ACC-04-24, ACC-05-22, ACC-08-18, ACC-13-16, ACC-05-20, ACC-NEG-19Accepted in Wave 1. Residual: cost is bounded, not eliminated — a Wave-1 build is billed to the owner's own GitHub account (ACCEPTANCE.md receipt criteria, ACC-05-20).
T-34EA Fleet node reports less containment than the run needs, and the run is admitted anywayApp Works admission reads the containment the node actually reported (FleetAgentTaskContainment, normalised before it is trusted — CONTRACTS.md:76, R-33): an App Work run is placed on a Fleet node only when the record includes the isolated home and no downgrade affects the workspace it will read; a missing or downgraded record places the run on a sandboxed runtime instead, or parks it with a reason the person can read. APW-04, APW-08 and APW-09 preparation runs each state the check they perform.ACC-NEG-21Accepted in Wave 1. Residual: the check adds a condition to the Fleet placement and never removes it (R-33), so a node reporting full containment is admitted exactly as before.

B-3 — The platform-written workflow, its EW_ Actions secrets and the ever-works-build-result artifact​

What crosses. The platform writes exactly one workflow file into the user's repository (.github/workflows/ever-works-build.yml, CONTRACTS.md:457), seals build values into Actions secrets named EW_<ENV NAME> (CONTRACTS.md:459), and reads back a workflow artifact it must treat as hostile (CONTRACTS.md:462). The repository can edit the file; anyone who can open a pull request can try to influence a run.

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-08IA build value leaks into logs or image metadata and ships inside the imageload and a separate push mean the secret-in-image check runs before any byte leaves the runner (APW-05-builds/plan.md:257-258, :218-224); the workflow itself contains no App env value, only references to EW_ secrets (APW-05-builds/spec.md:228-229); the check's implementation and its exclusion of throwaway build-service values (APW-05-builds/plan.md:817-833)ACC-05-15, ACC-05-05, ACC-05-18, ACC-13-01Accepted in Wave 1. Residual: the check covers image config and history, not file contents inside layers (APW-05-builds/plan.md:832-833) — a value copied into a file at build time is not detected; documented rather than hidden.
T-09T/SA fork pull request, or a hand-edited workflow, runs a job that can read secrets or push an imageThe build job runs only on same-repository pull requests (APW-05-builds/plan.md:172, :236-237); pull requests from other repositories never run a job that can read secrets or push images (APW-05-builds/spec.md:230-232); only workflow_run is subscribed, never push/pull_request webhooks for this purpose (APW-05-builds/plan.md:1093-1096); a hand-edited file is never silently overwritten — it takes the pull-request path (APW-05-builds/spec.md:227)ACC-05-06, ACC-05-04, ACC-05-02, ACC-NEG-05Accepted in Wave 1. Residual: a member with write access can always edit their own fork's CI; the platform's guarantee is about its own secrets, and the Actions-hygiene rule keeps inherited workflows disabled without ever switching Actions off (APW-02-fork-lifecycle/spec.md:293-297).
T-10T/IThe build artifact is forged or inflated to steer the platformThe artifact is untrusted input: only ever confirmed, never believed (CONTRACTS.md:462, APW-05-builds/plan.md:753-755); a strict schema, ≤ 64 KB download, ≤ 8 KB JSON, digest pattern ^sha256:[a-f0-9]{64}$; the digest is confirmed against the registry and a mismatch is digestMismatch (APW-05-builds/spec.md:276-278)ACC-05-07, ACC-05-21, ACC-05-28Accepted in Wave 1. Residual: while a private image has no pull token yet, the Build stays digestUnconfirmed rather than trusting the job log (APW-05-builds/plan.md:756-759) — a visible delay, deliberately preferred over believing repository-controlled text.
T-11IThe per-run verification secret (EW_VERIFY__PROMPTED) outlives the run and is readable laterIt is one sealed secret holding already-set prompted values for a single run, deleted on the Build's terminal transition and swept if orphaned (CONTRACTS.md:461, APW-05-builds/plan.md:799-804); the run shreds its env file and values never reach the App Work (APW-05-builds/spec.md:338-341); an App spec env name that would collide with the reserved secret name is refused (APW-05-builds/plan.md:804)ACC-05-13, ACC-04-23, ACC-07-31, ACC-05-23Accepted in Wave 1. Residual: an orphaned secret is deleted within a bounded sweep window (startedAt + 30 min + 10 min) rather than instantly; the window is stated in the plan, not implied.
T-12EA Build runs somewhere it should not, or with more privilege than declaredNo Build runs on infrastructure that hosts Ever Works itself or any production product (APW-05-builds/spec.md:212, README.md:175); every third-party action is pinned to a 40-character commit hash (APW-05-builds/spec.md:235); managed in-zone builds are sandboxed with an egress allowlist and their own registry space, and only arrive in Wave 3 behind LG-24 (APW-05-builds/plan.md:850-865, CONTRACTS.md:67)ACC-05-05, ACC-05-26, ACC-05-27, ACC-10-25Accepted in Wave 3 for managed builds (LG-24, APW-10-apps-hosting-tier/spec.md:206); Wave-1 builds are the user's own runner minutes and the user's own blast radius.

B-4 — User-supplied kubeconfigs dialled by the cluster-op worker​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-13EA kubeconfig points the platform at an internal address, a metadata service or a local commandRefused before any connection attempt when the credential shells out or uses a token file, a client certificate/key, a proxy or skipped verification (APW-06-app-runtime/spec.md:252-255); the server must be https and every resolved address must be public (:256-259); the guard denies private, loopback, link-local, shared and reserved ranges, pins the validated IP and does not follow redirects (APW-06-app-runtime/plan.md:871-888); the same guard applies to an ingress address before it becomes a DNS record (:888)ACC-06-02, ACC-06-03, ACC-06-28Accepted in Wave 1. Residual: EVER_WORKS_APPS_CLUSTER_PRIVATE_ALLOWLIST deliberately re-permits operator-declared private ranges for self-hosted installations and e2e (CONTRACTS.md:424) — an explicit operator decision with a named variable, never a silent default.
T-14EThe platform dials, or holds, a cluster from the wrong processAll App cluster I/O runs in background tasks on the cluster-op queue; the API holds no kubeconfig and never dials — the generic plugin-settings route skips connection validation for kind app (APW-06-app-runtime/plan.md:890-914); production refuses any App cluster job unless the operator declares the worker isolated (CONTRACTS.md:423, APW-06-app-runtime/plan.md:900-902)ACC-06-04, ACC-06-43, ACC-06-05Accepted in Wave 1. Residual: the isolation of that worker is an operator attestation (EVER_WORKS_APPS_CLUSTER_WORKER_ISOLATED); the network design behind it lives in the private operations repository (§5).
T-15IThe kubeconfig, or what it reaches, is disclosed in a response, log, Activity row or the repositoryIt is stored encrypted for the App Work and never returned by any endpoint (APW-06-app-runtime/spec.md:252-255); Activity holds names, states, durations and links — never env values, kubeconfig content, tokens or log text (:492); logs are redacted, never persisted (ACC-06-34); the kubeconfig string must not appear in the Work Repository, build logs or Activity (ACCEPTANCE.md:514-517)ACC-06-41, ACC-06-34, ACC-E2E-10Accepted in Wave 1. Residual: the end-to-end assertion (ACC-E2E-10(a)) only runs in the nightly lane with a real user cluster (ACCEPTANCE.md:510-517).
T-16TA cluster-op job touches workloads or namespaces it does not ownOne namespace per App Work, named once and never renamed; a namespace belonging to another Work, or holding objects Ever Works did not create, is refused (APW-06-app-runtime/spec.md:289-291); verification targets are per-attempt namespaces with a TTL, no Ingress, no DNS and no PVC, destroyed whole (CONTRACTS.md:308); the platform never applies manifests on the managed tier (R-5, CONTRACTS.md:48)ACC-06-48, ACC-04-21, ACC-06-10, ACC-06-36Accepted in Wave 1. Residual: on Your cluster the platform is a guest with the credential the owner gave it; containment is namespace-scoped, not cluster-scoped, and the delete path keeps volumes and dependencies unless explicitly confirmed (R-15, CONTRACTS.md:58).

B-5 — Tenant workloads on Ever Works Apps​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-17EA tenant app escapes its namespace, reaches another tenant, the platform or the cluster control planeOne namespace per App Work, created with its security profile, network policies and quota before any workload (APW-10-apps-hosting-tier/spec.md:264-266); every workload runs on the sandboxed runtime, as non-root, with capabilities dropped, default seccomp and no service-account token (:267-269); networking is deny-by-default both ways (:270-273); gate items LG-02, LG-04, LG-05, LG-06, LG-07, LG-11, LG-12 (:184-194)ACC-10-08…ACC-10-16, ACC-10-26, ACC-10-46, ACC-06-38, ACC-10-09 (known-dirty control)Accepted in Wave 2, and only while the gate is green: the tier is closed by default (APW-10-apps-hosting-tier/spec.md:213-215), the installation ceiling defaults to off (CONTRACTS.md:418) and consumers ask AppsTierPolicy.isOpen() rather than reading the variable (R-5, CONTRACTS.md:48).
T-18IA platform, organization or other-App-Work credential is delivered into a tenantNo credential issued to the platform, an organization or another App Work is ever delivered into a tenant — only per-App-Work credentials; the controller refuses a deployment whose environment matches a platform credential fingerprint (APW-10-apps-hosting-tier/spec.md:276-278); secrets travel sealed to the controller's key and the platform never creates a secret in the zone (:287-290); the platform's own control credential can only write desired state in one namespace (LG-12, :194)ACC-10-28, ACC-10-15, ACC-10-16, ACC-10-46Accepted in Wave 2. Residual: "fingerprint" detection covers configured platform credentials; a new credential added operationally and not configured into the fingerprint list is out of scope until added — an operational obligation recorded in the private repository.
T-19D/IA tenant app is abused for spam, mining or flood; its data mixes with another tenant'sMail and mining ports blocked (LG-08, :190); quotas, limits, no load balancer or node port (LG-09, :191); abuse controls, bandwidth limits and a signal ≤ 120 s (LG-19, :201); tenant-only data servers with a restore test (LG-14, :196); per-App-Work dependencies are never the platform's own data services (README.md:185-189, D8) and managed outputs never reach the platform (APW-07-app-env-and-dependencies/plan.md:572-583); every App Works background family also has an operator kill switch read by its dispatcher and failing closed — with the switches off, App Works stop changing anything and nothing is deleted (CONTRACTS.md:73, R-30)ACC-10-38…ACC-10-44, ACC-10-29, ACC-07-26, ACC-07-27, ACC-06-42, ACC-NEG-18Accepted in Wave 2. Residual: abuse detection is signal-based with an operator rota (LG-19 is Both: partly attested), so response time is an operational property, not a code guarantee.
T-20EA tenant image is replaced, or an unsigned/foreign image runs in a tenant namespaceEvery image is copied by digest into the App Work's own registry space, scanned and signed by the zone before first use; only signed images from that space may run (APW-10-apps-hosting-tier/spec.md:310-312); unsigned or foreign-signed images are refused (LG-13, :195); a fixable critical vulnerability is refused at promotion unless an operator allowance is recorded and expiring (ACC-10-30)ACC-10-17, ACC-10-30, ACC-05-28Accepted in Wave 2. Residual: the allowance mechanism is deliberately additive — an operator can admit a specific image for a bounded period, and that decision is auditable rather than impossible.

B-6 — The runtime-loaded catalogs as a supply chain​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-21T/SA poisoned catalog row or Blueprint repository steers what gets built, hosted or shownEvery row is validated and sanitized per catalog.md §3 — HTML stripped, patterns enforced, and a row whose SPDX classifies red in the registry is dropped whatever the row claims (R-3, CONTRACTS.md:46; APW-03-app-spec-and-catalog/plan.md:213); the listing never overrides what a template repository says about itself (README.md:143-148); license classes gate hosting per target (D13, README.md:241-250)ACC-03-17, ACC-03-46, ACC-03-48, ACC-13-15, ACC-NEG-01, ACC-NEG-02Accepted in Waves 1–2. Residual: verification is a five-pass human-plus-CI process (two consecutive failures unverify, ACC-13-15) — a curation process, not a cryptographic guarantee, and the managed tier's verified-blueprints scope exists for exactly that reason.
T-22ECatalog data (upstream names, aliases, links) is used to make the platform fetch an attacker hostThe catalog service has exactly two fetch sites — catalog files and Blueprint repository files — both built from validated owner/repo values; upstreams[].repo, aliases and links are never passed to a fetch, asserted by a test that fails on any other host or repository (APW-03-app-spec-and-catalog/plan.md:214); the primary read is tokenless with an 8-second timeout and sizes are capped (APW-03-app-spec-and-catalog/spec.md:253, :255)ACC-03-18, ACC-03-16, ACC-03-17Accepted in Wave 1. Residual: an unavailable catalog degrades to an empty, flagged result rather than an error (APW-03-app-spec-and-catalog/spec.md:255) — availability is preferred over failing closed, and the flag is user-visible.
T-23TThe launcher catalog injects a hostile tile (script URL, non-https address, over-long list)No catalog field is ever interpreted as markup or script and icons render as images only (APW-11-app-launcher/spec.md:205); a javascript:/http: address or an over-limit list produces no tile (ACC-11-08); tiles open with no opener and no referrer and the stored address is the only one used (APW-11-app-launcher/spec.md:252); when the catalog cannot be read the component renders the last good list it stored, and nothing older than 7 days (:309-310)ACC-11-08, ACC-11-23, ACC-11-39, ACC-11-27Accepted in Waves 1–2. Residual: the Ever Works platform list is readable signed out (CONTRACTS.md:350), so its integrity rests on the catalog organization's own controls (§5).

B-7 — Delegated Ever ID tokens and cross-origin launcher reads​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-24S/EA third-party origin replays a delegated token to read a person's App Works, or escalates itDelegated tokens are admitted only on routes carrying @DelegatedRead(scope) (R-19, CONTRACTS.md:62), with audience ever-works and a lifetime ≤ 3,600 s, and a decorated handler without the scope answers 403 insufficientScope (CONTRACTS.md:317); reads are accepted only from an operator allow-list of at most 50 exact https origins, and everything else is refused and treated as signed out (APW-11-app-launcher/spec.md:305-308); a delegated read never opens a session and can never change arrangement or exposure (APW-12-ever-id/spec.md:303, APW-11-app-launcher/spec.md:305-306)ACC-11-38, ACC-11-37, ACC-12-33, ACC-12-34, ACC-12-35, ACC-11-36Accepted in Wave 2. Residual: the allow-list is operator-maintained configuration (CONTRACTS.md:431); a mistake there is a configuration error, not a code bypass, and ACC-11-38 is the regression test.
T-25IThe platform session cookie or a token leaks to an app host, a launcher host or a URLWhere a managed address shares the platform's registrable domain, isolation is carried by host-only __Host- Secure cookies on platform routes, no platform session cookie on app hosts, and app hosts that never serve platform pages (R-16, CONTRACTS.md:59; README.md:222-227); the dedicated Public-Suffix-List apex stays supported and keeps its APEX_NOT_ON_PSL / PSL_UNREACHABLE probes (LG-15, APW-10-apps-hosting-tier/spec.md:197); no launcher request places a credential in a URL (ACC-11-24)ACC-11-24, ACC-11-36, ACC-06-27, ACC-13-20Accepted in Waves 1–2. Residual: an installation that chooses the shared default domain carries this work explicitly and can move to a PSL apex at any time — both shapes are kept, neither is deprecated (D10, README.md:199-227).

B-8 — The non-production EVER_WORKS_E2E_FAKES switch redirects the Git provider base URL​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-26S/TThe fake-GitHub switch takes effect in production, and the platform acts on attacker-controlled "GitHub" dataThe variable is honoured only when NODE_ENV is not production (CONTRACTS.md:437); it is set only in the two PR lanes (ACCEPTANCE.md:80, :132); the catalog service skips its tokenless read only when the switch is set outside production (APW-03-app-spec-and-catalog/plan.md:210); a unit test pins all three cases — on, off, and production-refused (APW-13-golden-paths/tasks.md:84-93)The EVER_WORKS_E2E_FAKES unit cases (APW-13-golden-paths/tasks.md:86-93) plus the PR lanes in ACCEPTANCE.md:80Accepted in Wave 1 as a deliberate test seam. Residual: it is a non-production hook by construction; there is no production code path that reads it, and production configurations must leave it unset (ACCEPTANCE.md:132).

B-9 — Upstream pull requests sent in the member's name​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-27S/RThe platform publishes code upstream in a member's name without that member's decisionEvery proposal and every later push requires an approval decided by the member whose GitHub account will publish it; no guardrail or autonomy mode can auto-approve it; it is never part of an "approve all" (R-18, CONTRACTS.md:61; APW-09-upstream-pull-requests/spec.md:240-245); the approval requirement cannot be switched off by any setting, file or API (:178); opening uses the member's own connection — never a platform token, an installation token or another member's (:252-256; CONTRACTS.md:289)ACC-09-11, ACC-09-14, ACC-NEG-06, ACC-E2E-08Accepted in Wave 2. Residual: an approval is a human decision made in the platform's UI; the platform's guarantee is that the decision is the member's, bound to a fingerprint of exactly what will be published, expiring after 72 h (APW-09-upstream-pull-requests/spec.md:249-251).
T-28IThe prepared diff carries secrets, the App spec, platform workflows, or unrelated fork customisationsThe prepared diff never contains the App spec, an Ever Works workflow, a protected path, .env*/key files or secret-like values (APW-09-upstream-pull-requests/spec.md:197-199); files not changed by the original change are marked and more than three refuse the proposal (:200-202); the body never mentions the fork's other customisations, the member's business, internal Task ids or Ever Works links (:226-227); upstream instruction files are read as untrusted and cannot widen what the agent may do (:203-207)ACC-09-06, ACC-09-05, ACC-09-07, ACC-09-10Accepted in Wave 2. Residual: the diff is still produced by an agent from a repository the member does not control; the controls are exclusion rules plus the member's own approval, and the acceptance scenario asserts the exclusions directly.
T-29DUpstream maintainers are flooded — the programme becomes a spam sourcePer member: at most 1 upstream pull request per upstream repository per 24 h, at most the App Work's own limit for open pull requests (default 3, hard ceiling 10), at most 3 across all upstreams per 24 h, at most 10 preparations per 24 h; per App Work one preparation at a time; at most 5 approved pushes per open pull request per 24 h (APW-09-upstream-pull-requests/spec.md:262-267); one active proposal per source Task (:186); a preparation that runs over 90 minutes fails (:213-215); the platform never merges, closes, reopens, labels or comments upstream (:284-285)ACC-09-15, ACC-09-16, ACC-09-21, ACC-09-19, ACC-09-22Accepted in Wave 2. Residual: rate limits are per member and per App Work, so a coordinated group of members could still be noisy across repositories — visible in Activity, and bounded by the per-repository 24 h rule.
T-30RThe platform signs a CLA/DCO in the member's name, or breaks a project's AI-disclosure ruleA CLA requirement detected in the project's guide, template or checks puts the proposal in Needs your signature (and DCO stops preparation) — the platform never signs (APW-09-upstream-pull-requests/spec.md:233-236); a guide that refuses AI contributions stops preparation with aiNotAccepted; the body always ends with the AI-disclosure line, in the project's own wording when it asks for one (:223-225)ACC-09-08, ACC-09-09, ACC-09-07Accepted in Wave 2. Residual: legal effect is the member's; the platform's contribution is refusing to proceed rather than deciding for them.

B-10 — User-supplied external endpoints the platform dials​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-31EA user-supplied S3/SMTP endpoint, webhook URL, Blueprint reference or app public URL points at an internal serviceExternal dependency endpoints are validated as public hostnames (no private, loopback or link-local address after DNS resolution) before any connection, matching the platform's existing SSRF posture (APW-07-app-env-and-dependencies/plan.md:569-570); the webhook receiver URL must pass the platform's existing safe-URL check and the secret is the owner's own setting, never generated or logged (APW-05-builds/plan.md:1087-1101); the ingress address is checked by the same guard before it becomes a DNS record (APW-06-app-runtime/plan.md:888); smoke requests never follow redirects (APW-06-app-runtime/plan.md:536)ACC-06-28, ACC-03-18, ACC-06-13, ACC-07-17, ACC-07-18Accepted in Wave 1. Residual: the guard is lexical plus DNS-resolution based; the platform's own roadmap item for DNS-rebinding-safe outbound HTTP is platform-wide and unchanged by this programme (../../security/THREAT-MODEL.md, §7 row H-09/H-10/H-11/M-23).

B-11 — Platform credentials and tenant data at rest, and the co-tenant read​

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-32IAn App env value, dependency output or identity leaks through an API, a log, Activity or the workspace backupNo stored or resolved value is returned, rendered, logged or placed in a URL (APW-07-app-env-and-dependencies/spec.md:204-206); values are encrypted per App Work (:207); Activity records names only (:210); log excerpts are redacted and stored secrets masked (APW-05-builds/plan.md:781-783); the workspace backup drops or redacts env values and dependency connection outputs and drops external identities whole (CONTRACTS.md:68, R-25); App Works Activity events default to never publish, because they carry repository names, paths and App Work identifiers (CONTRACTS.md:77, R-34); and deleting an account or an organization runs an idempotent cascade that removes platform-written EW_ secrets and webhooks, env values, dependency data and tier rows, and the identity links themselves (CONTRACTS.md:78, R-35)ACC-NEG-12, ACC-07-05, ACC-06-41, ACC-04-06, ACC-REG-15, ACC-NEG-20Accepted in Wave 1. Residual: backup classification is enforced by a collector test per epic (CONTRACTS.md:68); a new table added later without that classification is the failure mode the test exists to catch.
T-33EA co-tenant reads or changes another tenant's App Work through a new routeCross-tenant isolation stays where the platform already enforces it — application-layer ownership checks (../../security/THREAT-MODEL.md §1) — and every new App Works surface is required to carry the same check: upstream routes, app-status and target routes, env and dependency routes, evolve/delivery routes, upstream-PR routes and operator routes; every controller-owned read answers 404 for another account's App Work through the shared helper, never 403 (CONTRACTS.md:79, R-36)ACC-02-21, ACC-06-40, ACC-07-23, ACC-08-29, ACC-09-23, ACC-10-45, ACC-NEG-13, ACC-NEG-22Accepted in Wave 1, unchanged posture. Residual: this is the platform-wide application-layer model, not a new mechanism — a bug in an ownership check remains a cross-tenant breach, which is why the sibling document calls those checks security-critical.

B-12 — Non-human callers on human-only routes​

What crosses. API keys, Fleet run tokens, chat and MCP callers, command-line clients and Ever ID delegated tokens can all reach the same routes as a person. Five classes of action must not be reachable by a credential: spending money, deleting data, publishing outside the platform, changing a security posture, and accepting a legal obligation.

IdSTRIDEThreatControlVerifying acceptanceResidual risk · accepted in
T-35E/SA machine credential spends, deletes or publishes in a person's nameEvery such action is bound to an interactive session through the human-only guard (CONTRACTS.md:75, R-32): an API key, a Fleet run token and an Ever ID delegated token each answer 3 with the existing non-human-actor body and change nothing; the human-only column in CONTRACTS §4 is the list the MCP whitelist and the chat tool registry read, so a human-only route is never whitelisted (CONTRACTS.md:403-412); a typed confirmation is an extra field, never a substitute for the guard; an upstream pull-request approval is the author's own decision and is never bulk-approved (R-18, CONTRACTS.md:61); and the MCP server exposes neither the stored-data flag nor its confirmation, so no agent can destroy stored data through it (APW-01-app-work-kind/spec.md:439-443)ACC-NEG-17, ACC-01-14, ACC-09-11Accepted in Wave 1. Residual: a session is the unit of trust — a stolen session cookie is the person, which is the platform-wide posture (the sibling document puts a compromised tenant device out of scope). The guard narrows which credential may act, never which human is acting.

5. Deliberately kept in the private operations repository (pointer only)​

This document records requirements and evidence locations. The operational detail behind several controls is not public, by design, and is referenced here rather than copied (README §7 rule 10, README.md:373-376):

TopicKept in the private operations repositoryPublic pointer in this tree
Zone network design, egress identity, segmentation evidenceThe concrete design and its attestations (LG-02, LG-03, LG-07, LG-16, LG-22)APW-10-apps-hosting-tier/spec.md:184-198, APW-06-app-runtime/plan.md:900-902
The isolated cluster-op worker's network placementThe operator attestation behind EVER_WORKS_APPS_CLUSTER_WORKER_ISOLATEDCONTRACTS.md:423, APW-06-app-runtime/plan.md:900-902
Managed hosting location, capacity and its trade-offs (README Q1)The build-versus-rent analysis and the chosen locationREADME.md:388-391, README.md:267-268
Unpatched platform weaknesses and their reproductions (R-14)Exact reproductions; the public specs describe them genericallyCONTRACTS.md:57
Abuse rota, budget owner, retention number, operator drill evidenceNamed operational owners and the evidence for Attested gate items (LG-01, LG-03, LG-14, LG-16, LG-19, LG-21, LG-25)APW-10-apps-hosting-tier/spec.md:183-198, ACCEPTANCE.md (operator-evidence rows, e.g. ACC-10-09)
Platform-wide security audit findings and their convergence statusThe audit document and the finding ids (C-nn, H-nn, M-nn, L-nn)../../security/THREAT-MODEL.md §7

Nothing in this section is a waiver: each item above is a located obligation with a named owner class, and the gate item that carries it is listed in the pointer column.


6. Posture change — agents that read untrusted repositories​

The platform's stated posture is that the agentic CLI runs unsandboxed with the API process's permissions (../../security/THREAT-MODEL.md §1), which makes prompt injection inside the agent loop equivalent to remote code execution on the API host. That statement is unchanged and this document does not claim it is fixed.

What App Works adds is a rule for its own runs: an agent that reads an untrusted repository runs either in an enforcing sandbox or on a Fleet node the owner enrolled — and if neither exists, the run does not start.

RequirementWhere it is writtenWhat proves it
Provisioning runs execute only in a sandbox that enforces restricted networking; with none available the provisioning does not start (S10)APW-04-app-provisioner/spec.md:215-216ACC-04-04 (no restricted-network sandbox → no Run, Task or pull request)
That sandbox reaches exactly the repository host and public package/container registries, and nothing elseAPW-04-app-provisioner/spec.md:217-219ACC-04-05 (unit + nightly live isolation spec)
That sandbox receives repository contents and nothing else — no Git credential, platform token, env value, kubeconfig or Organization secretAPW-04-app-provisioner/spec.md:220-221ACC-04-06 (unit + nightly live isolation spec)
An agent run on an App Work Task executes only on a Fleet node the owner enrolled, or in an isolated run environment that receives no platform secret and restricts network access to the repository host and package registries; with neither, the run does not start (S15)APW-08-evolve-loop/spec.md:236-238ACC-08-08
A Fleet node is admitted only for the containment it actually reported: a missing record, or a downgrade affecting the workspace the run will read, places the run on a sandboxed runtime instead or parks it with a readable reason (R-33)CONTRACTS.md:76ACC-NEG-21
App spec checks execute only where the owner holds the blast radius, with a read-only token and no secrets; on a Fleet node only commands the owner admittedAPW-08-evolve-loop/spec.md:239-246ACC-08-09, ACC-08-10
Repository content is untrusted input, full stop: agents reading it run without secrets, and nothing from a repository runs on platform infrastructure outside a sandboxREADME.md:369-372 (rule 9)ACC-NEG-05, ACC-04-34, ACC-13-04
The upstream-contribution preparation run uses the same isolated environment, and the project's documented checks run inside it with no secretsAPW-09-upstream-pull-requests/spec.md:190-192, :208-212ACC-09-06, ACC-NEG-05

The honest limit. Only one pipeline enforces restricted networking today — claude-managed-agent maps networkingMode: limited onto an enforced sandbox policy, and every other pipeline treats it as advisory (APW-04-app-provisioner/plan.md:46). APW-04 therefore adds a capability flag (IPipelinePlugin.enforcesRuntimeNetworking, APW-04-app-provisioner/plan.md:626-629) and asks for it by capability rather than by plugin id; when no enabled pipeline has it, readiness reports provisioningUnavailable and nothing runs (APW-04-app-provisioner/spec.md:215-216). The ship gate for that claim is a live isolation spec with a known-bad control that must reach an unlisted host, run nightly (APW-04-app-provisioner/plan.md:813-827, ACCEPTANCE.md:45-46).

Explicit non-goals (kept, not removed):

  • Checks on a Fleet node and Builds in the user's own CI intentionally run on the owner's machine or the owner's runner — that is the blast-radius rule, not a gap (README.md:309-310).
  • A Build's own steps may reach the canary by design, because Builds run the repository's build steps on the user's runner; they must still carry no platform secret (APW-13-golden-paths/spec.md:225-226).
  • The managed tier's sandboxed runtime is required from Wave 2 (LG-04) and sandboxed in-zone builds from Wave 3 (LG-24); the split is a resolution, not a deferral of the requirement (CONTRACTS.md:67, R-24).

7. What this document does not close​

  1. No new resolution ids are invented here. The programme's binding decisions live in CONTRACTS.md §0 and are the lead's to extend. The rows this document would add there (a threat-register section and its entries) are supplied as ready-to-paste text in the accompanying shared-file request — never as a self-assigned R-28+. Since then R-37 has landed (CONTRACTS.md:80): CONTRACTS.md §10 is that register and already links this file. Its index ranges were written before this document existed and are reconciled by item 5 below.
  2. The platform-wide posture is unchanged. The unsandboxed general agent CLI, the in-process plugin model, the missing plugin signing and the DNS-rebinding gap are the sibling document's items; App Works neither fixes nor re-scopes them.
  3. The catalog organization's own controls are out of scope. ever-works/templates and ever-works/platforms are read at runtime (CONTRACTS.md:444-451); who may merge into them is an organization-permission question with its evidence in the private repository.
  4. Not every control has a runtime acceptance lane yet. Several rows above are verified by unit and controller specs first and by nightly/live lanes later; where that is the case the residual column says so rather than implying a live proof that does not exist.
  5. The threat ids in CONTRACTS.md §10's index do not match this file's ids. That index (ten boundaries, T-01…T-29) was written before this document; this file has twelve boundaries and 35 threats, with T-34 inside B-2 (Fleet containment, R-33) and T-35 inside B-12 (non-human callers, R-32). The exact replacement index — generated from this file's own tables, boundary by boundary — is supplied to the lead as a shared-file request. Until it lands, the tables in this file are the authority on threat ids; the ranges in §10 are an index that needs the one-line update, not a second register.

8. Revision log​

DateAuthorChange
2026-09-17App Works program (SK-06/XC-03)First version: assets, actors, eleven trust boundaries, 33 STRIDE threats with controls, verifying acceptance ids and accepted residuals; the untrusted-repository posture change (§6).
2026-09-17App Works program (SK-06/XC-03)Alignment pass: R-30…R-37 controls wired into the existing rows; B-12 (non-human callers on human-only routes, T-35) and T-34 (Fleet containment, R-33) added; §6 gains the containment requirement.
2026-09-26App Works specs laneT-03 note under B-1: the cloud evolve path is judged before the push and is off by default; the Fleet path, the unverified credential check and the merge-base residual (APW-08 T17).
2026-09-26App Works specs laneT-03 note narrowed: APP_WORKS_CLOUD_PUSH_ENABLED holds only finalizeRun; commitToRepo still pushes App Work feature branches after a pre-push checkPaths of its own files.
2026-09-26APW-08 T17T-03: the agent git tools answer to APP_WORKS_CLOUD_PUSH_ENABLED through finalizeRun's gate; off, an App Work commitToRepo / openPullRequest refuses naming FR-12 / T12 and publishes nothing.
2026-09-26APW-08 T17T-03: website-template sync refuses App Works in both funnels, whatever the switch says; the commitToRepo switch-on residual now says local-branch commits are not judged again.

Related documents. Program README · CONTRACTS · ACCEPTANCE · BUILD-READINESS · EXISTING-SUBSTRATE · deploy shapes · platform threat model · spec-tree verifier