mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-07 16:35:48 +01:00
## Thinking Path > - Paperclip lets people manage AI agents and their work. > - The manual AWS E2E workflow records browser and model evidence. > - Public repository Actions artifacts are not a restricted evidence store. > - Some chat evidence needs the existing private-history store. > - A target flag must not grant archive access or enable a public fallback. > - This pull request binds restricted runs to protected exact-source approval and retains their standard evidence with trusted transfer code. > - Operators can retain complete evidence without changing scanner verdicts or scenario outcomes. ## Linked Issues or Issue Description **What existing behavior does this improve?** Manual AWS E2E evidence retention for exact reviewed chat-feature selections. **Subsystem affected** The runner E2E manual workflow, standard evidence handoff and private-history transfer. **Current behavior** Manual cell and merged evidence use Actions artifacts. In a public repository, repository readers can download those files. Scheduled private history does not authorize a manual target to use its role. **Proposed behavior** Classify sensitive selections in the trusted workflow. Require one protected original-run approval. Verify existing private storage before target setup or model secrets. Retain scanned standard originals and final packaged results through a workflow-pinned runtime. Deny public artifact and history fallback on failure. **Reason and benefit** Preserve inspectable standard evidence in restricted storage without treating a private bucket as permission to retain credentials. **Additional context** Related source work is separate: #18067 changes paid runner routing, #18100 changes scoped input delivery, and #17888 changes report catalog parsing. This pull request does not include or revert those changes. ## What Changed - Add a trusted manual classification and exact run, attempt, workflow, target, selection and launcher approval contract. - Add a protected manual private job. Prepare a second workflow-pinned checkout and isolated publication dependencies before archive credentials. - Seal standard originals and final result bytes with exact inventories. Reject credential contamination, unscanned carriers and changed files. - Use existing immutable private-history archives and transfer receipts for cells and merged reports. Keep the existing bounds. - Use per-cell exact-key read sessions and a separate report writer. Check every inline policy against the 2,048-character STS limit. - Scan and seal fresh generated report logs and files with the actual report-step credential roots before transfer. - Require a positive nonprivate route for Actions uploads and public history. Private failures have no public fallback. Preserve normal catalog semantics for nonprivate selections with more than 32 IDs or duplicate IDs. - Authenticate generated-report fonts and every reserved trace-viewer static asset against the exact trusted producer path and bytes, including HTML and JavaScript. Keep standard cell evidence and unknown carriers closed. - Document the first eight supported IDs, deployment gates and the operator trust boundary. ## Verification - 57 new pure, actual-helper and actual-workflow-shell controls pass. - 50 affected existing workflow, routing, target and private-history controls pass. The final committed workflow security controls also pass. - Targeted helper/test and actual launcher noEmit checks pass. - `actionlint -shellcheck= -pyflakes= .github/workflows/runner-full-stack-e2e.yml` passes. - Parent `2f46336d7` required CI is green. The server 11/12 shard first failed on database cleanup/test timing and passed one bounded recheck with unchanged source. The original failure remains recorded. - The preserved docs-only parent `d721c170f` had 59 terminal, nonblocking checks and fresh Greptile 5/5. Three later review comments exposed a genuine static-report asset failure and nonprivate selector regression; their parent counterexamples remain recorded. - The reviewed parent passes 76 focused controls across nine files. The final dependency preflight successor passes all six affected controls, including two new actual `prepare` subprocess controls, and targeted helper/test noEmit. Unchanged suites were not repeated. A synthetic Node-only Playwright HTML/blob/JUnit report and the real dashboard renderer/brand stager pass the actual sealer, strict archive and immutable receipt path; only AWS transport is synthetic. No browser or product setup runs in that test. - Default cell fonts/SVGs, unknown report files, forged paths, altered static bytes, recomputed inventory tampering and registered credential matches remain rejected. Eligibility and remaining-byte checks run before body reads in both sealer and transfer validator; both independent parent read-order failures are preserved. - The pre-credential target comparison also binds the new generated-report asset helper byte for byte. A genuine tampered-dependency parent failure is preserved. - Six additional actual sealer/validator controls expose the standard-extension trace-owner bypass on the parent. All 34 affected controls pass on its correction, including the real producer/archive/receipt test; targeted noEmit passes. Ordinary dynamic report HTML outside the reserved trace directory is unchanged. - Final head `43683c4e0` passes both required gates, `ci / verify` and `ci / e2e`, in normal CI run `40849916302` attempt 1. All 59 rollup checks/statuses are terminal and nonblocking (55 success, two neutral, two skipped). - Fresh exact-head Greptile is 5/5; automated review is terminal and all technical threads are resolved. Human CODEOWNER approval remains a separate gate. Earlier source, genuine counterexamples and CI history remain preserved. - Full local build and live E2E were not run. This task prohibits local SDK/native/server builds and paid or AWS operations. Normal pull request CI must pass before merge readiness. - No existing artifact bodies, archives, media or provider reasoning were inspected. Synthetic owned fixtures prove the privacy boundaries. ## Risks - Deployment still needs the existing private bucket, role and protected environments. Both environments need the exact original-run approval variable. - Targets need the compatible handoff protocol and a separately reviewed exact launcher digest. Existing target branches do not become ready automatically. - Complete duplicated originals and packaged evidence can exceed existing archive limits. Such a transfer fails; files are not silently removed. - Required evidence omissions remain fatal to PASS. Safe failed evidence is retained with an explicit missing list and incomplete required-evidence verdict. Credential contamination still blocks all original uploads. Restricted storage does not waive PNG, HTML, blob or scanner checks. - This is operator-approved source execution. Target processes can inherit the job's OIDC request environment and may re-assume a role. Inline session attenuation is not isolation from malicious approved source. - Operator authorization must bind the actual exact source and original run. A proven administrator-controlled record may supply it without an environment reviewer UI. No new approval UI or environment change is required by this PR. - Required repository CODEOWNER review is still pending. Commented reviews and review requests are not approvals. This PR stays open and unmerged. - This PR does not deploy infrastructure, change IAM, dispatch workflows, publish report payloads, change grades or transfer prior scenario passes. ## Model Used OpenAI `gpt-6.1-sol` in Codex. Used code execution, source analysis and tool calls. The host does not expose the context window size. Independent peer review used the same model family in a separate agent. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
154 lines
8.9 KiB
Markdown
154 lines
8.9 KiB
Markdown
# Restricted evidence for manual AWS E2E runs
|
|
|
|
The manual AWS workflow has a separate restricted evidence route. It uses the
|
|
existing private-history bucket, protected environments, OIDC role and bounded
|
|
archive transfer. It does not change the scheduled private-history lane.
|
|
|
|
GitHub Actions artifacts in a public repository are readable by repository
|
|
readers. They are not an organization-private evidence store. The restricted
|
|
route never uploads raw cell evidence or a merged report to Actions, S3 public
|
|
history, or Pages. This stays true on setup failure, launcher failure and report
|
|
failure. Previously staged files do not enable a public fallback.
|
|
|
|
## Supported first selections
|
|
|
|
The first supported selection is an exact subset of these execution IDs:
|
|
|
|
- `chat-features.runner-opencode.local.activity.agent-feedback`
|
|
- `chat-features.runner-opencode.local.activity.work-timeline`
|
|
- `chat-features.runner-opencode.local.companies.import-preview`
|
|
- `chat-features.runner-opencode.local.navigation-preferences.dismiss-announcement`
|
|
- `chat-features.runner-opencode.local.tasks.completion-with-gate`
|
|
- `chat-features.runner-opencode.local.tasks.private-task`
|
|
- `chat-features.runner-opencode.local.secrets.personal-secret`
|
|
- `chat-features.runner-opencode.local.agents.choose-primary`
|
|
|
|
These IDs require the reviewed AWS Fleet route. Broad chat suites, mixed
|
|
unsupported IDs, reruns and missing approvals fail closed. All chat-feature IDs
|
|
are classified as restricted by trusted code. A target descriptor cannot opt out.
|
|
Other manual selections keep the existing Actions route only after a trusted
|
|
per-cell check confirms that the actual selected execution is not restricted.
|
|
Selector whitespace and exclusivity follow the catalog producer.
|
|
|
|
A case that needs invitation-capability handling or other new producer support
|
|
is not supported merely because restricted storage exists. It needs its own
|
|
reviewed source, evidence contract and exact operation approval.
|
|
|
|
## Deployment and operator gates
|
|
|
|
This source change alone does not configure a role, bucket, environment, target,
|
|
or run. Before a supported run, the operator must:
|
|
|
|
1. Deploy this workflow and its helpers together on the protected default branch.
|
|
2. Keep the existing numeric actor allowlist and protected default-branch checks.
|
|
3. Keep `runner-e2e-private-paid` and `runner-e2e-private-history` restricted to
|
|
the default branch. Establish administrator-controlled approval for the exact
|
|
source and original run. A reviewer UI may supply this control but is not
|
|
mandatory. Prove the actual control and runtime contract before admission.
|
|
4. Provide the existing private-history role ARN, AWS region and bucket variables
|
|
in those environments. The existing role must support the existing bounded
|
|
prefix and bucket-policy, ownership, public-access and retention reads.
|
|
5. Provide `RUNNER_E2E_MANUAL_PRIVATE_APPROVALS_JSON` through administrator-controlled
|
|
configuration available to both protected jobs. Approve the exact resolved
|
|
workflow SHA, target SHA, original run ID,
|
|
attempt `1`, selected execution IDs and launcher SHA-256.
|
|
6. Use a reviewed compatible target. Its private handoff and policy modules must
|
|
match the workflow implementation byte for byte. Its launcher digest must
|
|
match the protected approval. Earlier target branches do not gain this
|
|
protocol automatically.
|
|
|
|
Classification happens before the protected job. It grants no archive authority.
|
|
The administrator-controlled record must bind the actual original run ID before
|
|
target dependency setup or archive credentials. Prove who can change that record
|
|
and that each job consumes the exact approved record. An environment reviewer
|
|
gate is one way to govern authorization; its UI is not required. A missing or
|
|
stale row still fails closed before target dependency setup, archive credentials,
|
|
model credentials or fixture secrets. There is no wildcard approval.
|
|
|
|
The variable has this closed shape (all values below are placeholders):
|
|
|
|
```json
|
|
{
|
|
"version": 1,
|
|
"approvals": [{
|
|
"workflowSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
"targetSha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
"runId": "123456789",
|
|
"attempt": "1",
|
|
"executionIds": ["chat-features.runner-opencode.local.activity.agent-feedback"],
|
|
"protocol": "paperclip.manual-private-evidence/v1",
|
|
"launchSha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
|
}]
|
|
}
|
|
```
|
|
|
|
## Trust and credential lifetime
|
|
|
|
The workflow checks out its own immutable `github.sha` into a separate directory.
|
|
It prepares pinned publication dependencies with `--ignore-scripts` and a
|
|
separate store before archive credentials. Transfers use that checkout's
|
|
absolute helper, tsx and archive-script paths. They do not load the target's
|
|
node_modules or an ambient Node loader. The target executes only after the
|
|
protected approval and private-storage preflight pass.
|
|
|
|
The AWS action returns session credentials as step outputs, not job-wide
|
|
environment exports. Only trusted preflight and transfer steps receive those
|
|
outputs. Transfers require an explicit complete session and disable EC2 metadata
|
|
fallback. A failed or expired session fails retention. It never enables an
|
|
Actions upload. Exact-key session policies limit the intended transfer calls. Each current cell
|
|
uses its own two-object read session; the report writer uses a separate session.
|
|
Every generated policy is checked against the 2,048-character STS limit before
|
|
the credential action. No wildcard object access is added.
|
|
|
|
This is **operator-approved target execution**, not a sandbox for malicious
|
|
source. The protected job has OIDC permission. Its target launcher can inherit
|
|
the GitHub OIDC request environment, and the existing harness copies its process
|
|
environment into server/native children. A target that can request a new OIDC
|
|
session may re-assume the role. An inline session policy does not prevent that.
|
|
Reviewers must approve the complete exact target, not just its evidence flag.
|
|
This change does not alter IAM, OIDC trust, host roles or credential duration.
|
|
|
|
## Evidence and failure rules
|
|
|
|
The launcher keeps its ordinary standard evidence in an owned temporary root.
|
|
It preserves the original framework result before launcher result updates. It
|
|
also seals final packaged results after cleanup and campaign finalization.
|
|
The transfer validates exact file inventories and hashes before archiving.
|
|
It excludes instance databases, workspaces, credential registries, auth files,
|
|
raw capture directories and arbitrary files outside the standard evidence scope.
|
|
Free-form launcher console capture is not an approved retained carrier.
|
|
|
|
The existing credential scanners and PASS PNG, HTML, blob and snapshot checks
|
|
still apply. Original text, ZIP and media bytes receive those scans before
|
|
retention. Raw and encoded registered roots and provider-shaped names are also
|
|
rejected from original paths and inventories. Unknown extensions and SVG files
|
|
that the ordinary packager does not inspect cannot become complete originals.
|
|
Files cannot be silently dropped to meet a bound. Credential contamination,
|
|
unsupported carriers or a changed inventory stop the transfer. Missing required
|
|
PASS files still convert the attempt to infrastructure FAIL. The private inventory
|
|
retains all safe available originals and records `requiredEvidenceComplete: false`
|
|
and the exact missing list. Its `complete` field means the available file inventory
|
|
is complete; it does not certify PASS evidence completeness. Failed framework
|
|
attempts do not claim that PASS evidence checks ran. No file is synthesized and
|
|
no secret-bearing original is uploaded just because the bucket is private.
|
|
|
|
The existing archive bounds remain unchanged: at most 256 MiB of source files,
|
|
4,097 archive entries and 264 MiB transferred archive bytes. Duplicated original
|
|
and packaged files count toward those bounds. A run that exceeds a bound does
|
|
not have complete retained evidence and needs an explicit disposition.
|
|
|
|
Private objects use immutable conditional puts and version receipts under
|
|
`runner-e2e-private/bounded-v1/campaigns/gha-RUN_ID-1/`. Each cell has a hash-derived
|
|
object name. The report reads only the approved current cells and verifies each
|
|
archive against its retained transfer digest. Fresh merged HTML, blob, normalized output and report logs receive a final
|
|
standard-file scan and sealed inventory with the actual current report-step
|
|
credential roots, including its explicit AWS session. The report uses the same
|
|
raw, encoded-root and provider-shape checks before transfer. It retains the
|
|
scanned report in the same restricted store. A report error stays a report
|
|
error; retention does not change its grade or manufacture a public page.
|
|
|
|
Authenticated retrieval uses the existing private-history operator machinery
|
|
and approved bucket access. This PR does not grant a reader role or perform an
|
|
upload. Actual deployment, environment approval, compatible target fingerprints,
|
|
private storage access and one exact run approval remain operational gates.
|