Early-partner security review
What a team admin should verify before using Viewport for governed agent work.
Use this page when an admin or security reviewer asks, "what exactly are we trusting for the first rollout?"
The launch path is intentionally narrow:
Slack or GitHub event
-> committed .viewport route and policy
-> hosted Viewport admission
-> self-hosted vpd worker
-> human approval gate
-> brokered GitHub/Slack side effect
-> receipts and run detailDo not broaden the rollout until one small repository and one team can complete that path end to end.
Trust Boundary
vpd runs work. Hosted Viewport decides whether hosted work is allowed.
For hosted Viewport, the server is the authority for:
- workspace, organization, team, and membership checks;
- route and policy sync from
.viewport/; - workflow publication and run admission;
- worker pairing, revocation, and claimability;
- credential and side-effect grants;
- approval state;
- run receipts and audit views.
The self-hosted worker is authority for local execution facts only:
- which agents and tools are installed locally;
- local model keys and package credentials provided by the operator;
- process exit codes, logs, and tool output;
- usage metadata reported by the adapter.
Worker-reported evidence is useful, but hosted policy and tenant boundaries must be derived from server-side state.
Minimum Controls For The First Team
Before inviting more users, verify these controls:
| Control | Expected launch posture |
|---|---|
| Repository scope | GitHub App installed only on sandbox or low-risk team repos. |
| Route source | .viewport/routes/*.yaml committed in Git and synced without signature errors. |
| Policy source | .viewport/policy.yaml committed in Git, with one explicit human plan-review gate. |
| Reviewer routing | Reviewer tags resolve to real members of the owning team. |
| Worker pairing | One persistent polling worker paired to the selected workspace and workdir. |
| Branch boundary | Agent publishes to agent/** or another non-protected branch pattern. |
| Provider writes | GitHub/Slack writes happen through configured provider grants, not broad agent-held org tokens. |
| Support evidence | Support packets contain sanitized ids and doctor output, never raw tokens or private keys. |
Evidence To Inspect After The First Run
Run detail should make the run explainable without shell access:
- trigger provider, route, policy path, ref, SHA, and policy hash;
- selected team and workflow;
- worker claim and workspace root;
- checkout or context resolution receipt;
- plan node output before implementation;
- approval decision, approver, and timestamp;
- implementation/test result;
- bounded branch or proposal;
- GitHub PR URL when a PR was opened;
- Slack permalink when a completion message was posted;
- usage and token metadata when the adapter reports it;
- cleanup receipt.
If any of those are missing, treat the rollout as not ready for broader team use. Fix the missing evidence or document the explicit reason before continuing.
Common Denials That Should Be Clear
The product should fail closed with an actionable reason for these cases:
| Case | Expected result |
|---|---|
.viewport/ is gitignored | vpd check warns before sync. |
| Reviewer tag matches nobody | Policy sync is blocked before a run waits on nobody. |
| Worker is paired to a different workspace | Claim or sync is denied. |
| Worker was revoked | New claims are denied. |
| GitHub App lacks repo access | Checkout or PR side effect fails with provider-permission guidance. |
| Slack source timestamp is missing | Completion may post to the fallback channel; run detail remains source of truth. |
| Provider action is denied or fails | Receipt/error copy names the provider, credential, and next check. |
UI hiding is never the enforcement boundary. If a user can reach an API route they are not authorized for, the backend must still deny it.
Operating Rules
- Start with one team, one repo, one Slack channel, and one worker.
- Keep production deploys, protected branch writes, and broad repo grants out of the first proof.
- Keep a named owner for the worker process and host.
- Restart the worker through your normal process manager after host reboot.
- Re-run
vpd worker doctor --jsonafter changing the pair, workdir, local model key, or provider setup. - Verify a new Slack route with a live source-thread completion before claiming that route is ready.
- Verify a new provider with one small run before adding it to a customer proof.
What To Tell Security Reviewers
This is a fair launch statement:
Viewport governs agent work by syncing declarative policy from Git, routing work through hosted admission, executing on a self-hosted worker, requiring a human gate for the first rollout, and recording provider receipts.
Avoid stronger statements unless your workspace has separate proof:
- do not claim managed runners are available;
- do not claim automated billing enforcement;
- do not claim SOC 2 readiness or full audit export;
- do not claim tamper-proof audit;
- do not claim every Slack route replies in-thread until that route is tested;
- do not claim local worker secrets are protected from a malicious machine administrator.
Support Packet
When asking Viewport for help, include:
vpd worker doctor --json > /tmp/vpd-worker-doctor.json
vpd status --json > /tmp/vpd-status.json
vpd check . --json > /tmp/vpd-check.jsonShare sanitized files plus the workspace name, team name, route name, run id, provider receipt id, and screenshots from run detail.
Never share raw provider access tokens, model API keys, pairing codes, bootstrap tokens, claim tokens, lease tokens, or worker private keys.