Skip to content

Phase 5 enterprise track (code GO, release held on owner gates)#313

Closed
samrusani wants to merge 1 commit into
mainfrom
codex/v0140-phase5-enterprise-track
Closed

Phase 5 enterprise track (code GO, release held on owner gates)#313
samrusani wants to merge 1 commit into
mainfrom
codex/v0140-phase5-enterprise-track

Conversation

@samrusani

Copy link
Copy Markdown
Owner

Summary

Team-built Phase 5 enterprise-track carrier, independently reviewed and independently re-verified by release engineering. Carrier receipt 4cf7e08b… recomputed from live bytes (exact match); 4,030 unit tests pass locally; the browser-clip capability's security properties were confirmed at the code level and its origin-binding test proven non-vacuous by mutation.

This PR runs committed-SHA CI only. It is a draft and holds the release. Versions remain 0.13.1. Phase 5 completion is NO-GO pending two owner gates: the 5.1.c independent external security review and the 5.4 real-host deployment receipt. No 0.14.0 cut, tag, or publish happens until those close and this CI is green.

Builds on the merged security fixes (#310, #311, #312). Delivers: a short-lived, origin-bound, one-time browser-clip capability (raw value never stored, atomic single-use consume, migration 0094); Stage A security evidence; executed backup/restore/upgrade/DR evidence on SQLite and PostgreSQL 16; a hardened review dashboard; and a single-tenant deployment contract with validation tooling.

Upgrade Overview

Protected Areas

  • Memory schema
    • Additive migration 0094 (browser_clip_capabilities table); sqlite_schema.py, sqlite_store.py, vnext_store.py, and vnext_stores/* gain the capability store methods. No change to existing table semantics.
  • Continuity APIs
    • routers/vnext_memories.py gains the origin-bound browser-clip issue/consume path behind the authenticated boundary; no existing route contract shape changes.
  • No MCP tool, dependency, or version change (versions held at 0.13.1)
  • Immutable release records and the protected SQLite memory_access.py are unchanged

Compatibility Impact

Additive only. Existing routes, tools, and stored data are unaffected. The new browser-clip capability is a new, authenticated, origin-scoped feature; the previous reusable-token clipper behavior is replaced by the one-time capability (the fix for the security-review finding).

Migration / Rollout

One additive Alembic migration (0094) creating the browser_clip_capabilities table; the SQLite bootstrap gains the same table. No existing data is migrated or destroyed.

Operator Action

None for existing deployments. The single-tenant deployment guide and ops-evidence tooling are new documentation and scripts; using them is optional and covered by the 5.4 owner gate.

Validation

Carrier receipt recomputed to 4cf7e08b (exact); 4,030 unit tests pass; control-doc truth and release_check pass at 0.13.1; browser-clip security verified and its tests proven non-vacuous. Integration, web, browser, and ops drills run on this committed SHA via CI.

Rollback

Revert the carrier commit and run the 0094 downgrade (drops the browser_clip_capabilities table). No existing data is affected by rollback.

Team-built, independently reviewed, and independently re-verified by
release engineering. Integrates the enterprise-track work on top of the
merged security fixes (PRs #310, #311, #312): a short-lived, origin-bound,
one-time browser-clip capability (raw value never stored, atomic
single-use consume, no cross-origin replay; migration 0094); Stage A
security threat model, authorization and input-validation sweeps, and
secret-handling and dependency-posture evidence; executed backup, restore,
portable export/import, v0.12-to-current upgrade, and disaster-recovery
evidence on SQLite and PostgreSQL 16; a hardened review dashboard with an
authenticated /vnext operator path; and a single-tenant deployment
contract with validation tooling.

Versions remain 0.13.1. This commit runs committed-SHA CI only; it does
not cut 0.14.0, tag, or publish. Phase 5 completion stays NO-GO pending
two owner gates: the 5.1.c independent external security review and the
5.4 real-host deployment receipt. Stage A is not Stage B; the checked-in
deployment contract is not real-host evidence.

Verified by release engineering: carrier receipt recomputed from live
bytes (4cf7e08b, 20,845 bytes, exact match); 4,030 unit tests pass;
control-doc truth and release_check pass at 0.13.1; the browser-clip
security properties confirmed at the code level and the origin-binding
test proven non-vacuous by mutation.

Alice-Carrier-Receipt-SHA256: 4cf7e08b6faddd681daf2217fe3c7184746be4ca34cf7b71098637ce7eb2ed34
Alice-Build-Report-SHA256: af85f5497fb1e0f23889233632a4fe0d4bb771f18a0b9637cedde2e9bb95c9e5
Alice-Review-Report-SHA256: 138fdfca00c2a4652e800964227a185e43b8ea3fbf628ba01bdc5e062f78ea0a
});

it("uses only an origin-bound one-time capability in visited-page code", () => {
expect(bookmarklet.startsWith("javascript:")).toBe(true);
const serializedDomain = JSON.stringify(domain);
const serializedSensitivity = JSON.stringify(sensitivity);

return `javascript:(async()=>{try{const endpoint=${serializedEndpoint};const user_id=${serializedUserId};const capture_capability=${serializedCapability};const expected_origin=${serializedOrigin};if(location.origin!==expected_origin){alert("This Alice clip is bound to "+expected_origin+". Prepare a new clip for this page.");return;}const user_note=prompt("Optional note","");const selection=window.getSelection()?.toString()??"";const body={user_id,url:location.href,title:document.title,selected_text:selection||null,page_text:selection?null:(document.body?.innerText??"").slice(0,20000),user_note:user_note||null,capture_capability,domain:${serializedDomain},sensitivity:${serializedSensitivity}};await fetch(endpoint,{method:"POST",mode:"no-cors",body:JSON.stringify(body)});alert("Alice clip request submitted. Verify it in the Alice Inbox.")}catch{alert("Alice clip request failed before submission.")}})();`;
const serializedDomain = JSON.stringify(domain);
const serializedSensitivity = JSON.stringify(sensitivity);

return `javascript:(async()=>{try{const endpoint=${serializedEndpoint};const user_id=${serializedUserId};const capture_capability=${serializedCapability};const expected_origin=${serializedOrigin};if(location.origin!==expected_origin){alert("This Alice clip is bound to "+expected_origin+". Prepare a new clip for this page.");return;}const user_note=prompt("Optional note","");const selection=window.getSelection()?.toString()??"";const body={user_id,url:location.href,title:document.title,selected_text:selection||null,page_text:selection?null:(document.body?.innerText??"").slice(0,20000),user_note:user_note||null,capture_capability,domain:${serializedDomain},sensitivity:${serializedSensitivity}};await fetch(endpoint,{method:"POST",mode:"no-cors",body:JSON.stringify(body)});alert("Alice clip request submitted. Verify it in the Alice Inbox.")}catch{alert("Alice clip request failed before submission.")}})();`;
const serializedDomain = JSON.stringify(domain);
const serializedSensitivity = JSON.stringify(sensitivity);

return `javascript:(async()=>{try{const endpoint=${serializedEndpoint};const user_id=${serializedUserId};const capture_capability=${serializedCapability};const expected_origin=${serializedOrigin};if(location.origin!==expected_origin){alert("This Alice clip is bound to "+expected_origin+". Prepare a new clip for this page.");return;}const user_note=prompt("Optional note","");const selection=window.getSelection()?.toString()??"";const body={user_id,url:location.href,title:document.title,selected_text:selection||null,page_text:selection?null:(document.body?.innerText??"").slice(0,20000),user_note:user_note||null,capture_capability,domain:${serializedDomain},sensitivity:${serializedSensitivity}};await fetch(endpoint,{method:"POST",mode:"no-cors",body:JSON.stringify(body)});alert("Alice clip request submitted. Verify it in the Alice Inbox.")}catch{alert("Alice clip request failed before submission.")}})();`;
const serializedDomain = JSON.stringify(domain);
const serializedSensitivity = JSON.stringify(sensitivity);

return `javascript:(async()=>{try{const endpoint=${serializedEndpoint};const user_id=${serializedUserId};const capture_capability=${serializedCapability};const expected_origin=${serializedOrigin};if(location.origin!==expected_origin){alert("This Alice clip is bound to "+expected_origin+". Prepare a new clip for this page.");return;}const user_note=prompt("Optional note","");const selection=window.getSelection()?.toString()??"";const body={user_id,url:location.href,title:document.title,selected_text:selection||null,page_text:selection?null:(document.body?.innerText??"").slice(0,20000),user_note:user_note||null,capture_capability,domain:${serializedDomain},sensitivity:${serializedSensitivity}};await fetch(endpoint,{method:"POST",mode:"no-cors",body:JSON.stringify(body)});alert("Alice clip request submitted. Verify it in the Alice Inbox.")}catch{alert("Alice clip request failed before submission.")}})();`;
const serializedDomain = JSON.stringify(domain);
const serializedSensitivity = JSON.stringify(sensitivity);

return `javascript:(async()=>{try{const endpoint=${serializedEndpoint};const user_id=${serializedUserId};const capture_capability=${serializedCapability};const expected_origin=${serializedOrigin};if(location.origin!==expected_origin){alert("This Alice clip is bound to "+expected_origin+". Prepare a new clip for this page.");return;}const user_note=prompt("Optional note","");const selection=window.getSelection()?.toString()??"";const body={user_id,url:location.href,title:document.title,selected_text:selection||null,page_text:selection?null:(document.body?.innerText??"").slice(0,20000),user_note:user_note||null,capture_capability,domain:${serializedDomain},sensitivity:${serializedSensitivity}};await fetch(endpoint,{method:"POST",mode:"no-cors",body:JSON.stringify(body)});alert("Alice clip request submitted. Verify it in the Alice Inbox.")}catch{alert("Alice clip request failed before submission.")}})();`;
const serializedDomain = JSON.stringify(domain);
const serializedSensitivity = JSON.stringify(sensitivity);

return `javascript:(async()=>{try{const endpoint=${serializedEndpoint};const user_id=${serializedUserId};const capture_capability=${serializedCapability};const expected_origin=${serializedOrigin};if(location.origin!==expected_origin){alert("This Alice clip is bound to "+expected_origin+". Prepare a new clip for this page.");return;}const user_note=prompt("Optional note","");const selection=window.getSelection()?.toString()??"";const body={user_id,url:location.href,title:document.title,selected_text:selection||null,page_text:selection?null:(document.body?.innerText??"").slice(0,20000),user_note:user_note||null,capture_capability,domain:${serializedDomain},sensitivity:${serializedSensitivity}};await fetch(endpoint,{method:"POST",mode:"no-cors",body:JSON.stringify(body)});alert("Alice clip request submitted. Verify it in the Alice Inbox.")}catch{alert("Alice clip request failed before submission.")}})();`;

def validate_caddyfile(text: str) -> None:
normalized = "\n".join(line.split("#", 1)[0].rstrip() for line in text.splitlines())
_require("alice.example.com" in normalized, "caddy_public_host_missing")
@samrusani

Copy link
Copy Markdown
Owner Author

Returning the carrier to the team. Committed-SHA CI on e8d2018 surfaced 6 issues (5 CI-portability/tooling: shallow-clone guard, missing tags for the ops upgrade drill, hardcoded venv path in migrate.sh, and a gitleaks false positive on an example env; plus 1 real browser-clip transport test failure at navigation.spec.ts:114). The carrier passed the local matrix only because the build env had full git history, tags, and a .venv. Fix and re-deliver a fresh uncommitted carrier with a new receipt; this exact 4cf7e08b carrier is not shippable. Full diagnosis handed off separately.

@samrusani samrusani closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants