Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
179 commits
Select commit Hold shift + click to select a range
d2497ae
Add APS render fix and TSJS resilience design spec
aram356 Aug 4, 2026
4f817d0
Rework design spec after review: settle the five architectural contracts
aram356 Aug 4, 2026
196f0b7
Revise design spec for the second review round
aram356 Aug 4, 2026
d92f801
Revise design spec for the third review round
aram356 Aug 4, 2026
42a0bdc
Rewrite design spec for the coordinated hard-cutover policy
aram356 Aug 4, 2026
5cca752
Close residual review deltas on revision 5
aram356 Aug 4, 2026
4166753
Revise design spec: adopt the 248fe9558 baseline and answer round five
aram356 Aug 4, 2026
517471c
Revise design spec for the sixth review round
aram356 Aug 4, 2026
b161168
Rewrite design spec self-contained for the seventh review round
aram356 Aug 4, 2026
0dc1a5d
Revise design spec for the eighth review round
aram356 Aug 4, 2026
fba6e7e
Revise design spec for the ninth review round
aram356 Aug 5, 2026
1b9753e
docs: finalize APS and TSJS resilience design
aram356 Aug 6, 2026
88f1432
Establish APS and TSJS implementation baseline
aram356 Aug 6, 2026
d08e305
Attach Ubuntu baseline evidence
aram356 Aug 6, 2026
5470764
Make APS descriptor a cross-language executable contract
aram356 Aug 6, 2026
1b3b649
Harden APS admission with typed drop reasons
aram356 Aug 6, 2026
1814b2a
Make auction outcomes explicit and provenance-safe
aram356 Aug 6, 2026
c4ce9fc
Project exact renderer identities across auction wires
aram356 Aug 6, 2026
5d66396
feat(aps): proxy the live creative runner safely
aram356 Aug 6, 2026
0fbd760
refactor(tsjs): enforce layering and external-global ownership
aram356 Aug 6, 2026
0db0d07
docs(tsjs): restore the toolchain upgrade task
aram356 Aug 6, 2026
71eda1e
Add transactional TSJS integration modules
aram356 Aug 6, 2026
3a5042d
Upgrade the TSJS package and TypeScript toolchain
aram356 Aug 6, 2026
4f0fb43
Establish TSJS runtime ownership and release identity
aram356 Aug 7, 2026
7450c0d
Add runtime and navigation session ownership
aram356 Aug 7, 2026
fa08031
Harden Task 9 ownership boundaries
aram356 Aug 7, 2026
6669800
Add bounded external readiness adapters
aram356 Aug 7, 2026
46d9697
Harden adapter queue admission and abort handshake
aram356 Aug 7, 2026
b3d4ece
Implement the slot registry and physical GPT cycle model
aram356 Aug 7, 2026
e928eaa
Harden slot ownership and GPT recovery transactions
aram356 Aug 7, 2026
0807e61
Fix GPT cycle queue admission races
aram356 Aug 7, 2026
cbae1a2
Harden GPT admission and recovery invariants
aram356 Aug 7, 2026
85403cd
Harden hostile GPT state transitions
aram356 Aug 7, 2026
1538666
Contain poisoned batch iterators
aram356 Aug 7, 2026
5695728
Add bounded renderer reservation service
aram356 Aug 7, 2026
cb991f3
Harden renderer reservation failure handling
aram356 Aug 7, 2026
dbf11bd
Harden reservation owner publication and cleanup
aram356 Aug 7, 2026
3ba7fde
Bind reservation owners to fresh generations
aram356 Aug 7, 2026
0231bdf
Implement render attempt lifecycle
aram356 Aug 7, 2026
b817f68
Harden render lifecycle transactions
aram356 Aug 7, 2026
a895d59
Bind render construction authority
aram356 Aug 7, 2026
fad69a0
Bind claims to exact render attempts
aram356 Aug 7, 2026
749ef99
Add renderer nonce registry
aram356 Aug 7, 2026
759235f
Add owned browser message channels
aram356 Aug 7, 2026
a4810c1
Implement direct APS renderer flow
aram356 Aug 7, 2026
a515040
feat(tsjs): implement direct ADM rendering
aram356 Aug 7, 2026
081cc72
fix(aps): align proxy and projection contracts
aram356 Aug 7, 2026
c60eaf9
ci(tsjs): enforce bundle budgets
aram356 Aug 7, 2026
4b93ea4
docs: make resilience plan execution atomic
aram356 Aug 7, 2026
e059f99
docs: clarify resilience contract guardrails
aram356 Aug 7, 2026
1c68d9f
Implement bounded cache rendering
aram356 Aug 7, 2026
6d9241e
Cover cache reservation authority
aram356 Aug 7, 2026
799aa6e
Refine the resilience implementation plan
aram356 Aug 7, 2026
06314ee
Complete the resilience plan review gates
aram356 Aug 7, 2026
b781a1b
Add the Universal Creative bridge dispatcher
aram356 Aug 7, 2026
f35248f
Harden cache rendering boundaries
aram356 Aug 7, 2026
d8a5340
Implement the Universal Creative bridge lifecycle
aram356 Aug 7, 2026
e2157b0
Harden the serialized PUC owner contract
aram356 Aug 7, 2026
2c61ff6
Harden PUC owner event boundaries
aram356 Aug 7, 2026
067ed54
Harden Universal Creative race boundaries
aram356 Aug 7, 2026
7c0544d
Cover APS buffered terminal ordering
aram356 Aug 7, 2026
6404b0b
Implement navigation-owned auction batches
aram356 Aug 7, 2026
9d47aa3
Validate the hard-cutover request API
aram356 Aug 7, 2026
c6de718
Harden auction settlement and slot snapshots
aram356 Aug 7, 2026
9b766c3
Wire the test-only direct auction API
aram356 Aug 7, 2026
e5a1341
Publish the hard-cutover TSJS types
aram356 Aug 7, 2026
55a2931
Harden direct auction identity boundaries
aram356 Aug 7, 2026
03f3725
Account for the direct auction request envelope
aram356 Aug 7, 2026
fce5781
Serialize direct auction bodies without publisher hooks
aram356 Aug 7, 2026
691fdd0
Prepare the real TSJS performance marks
aram356 Aug 7, 2026
0919e65
Exercise performance marks through browser composition
aram356 Aug 7, 2026
4f6a875
Guard collapsed GPT creative shell resizing
aram356 Aug 7, 2026
451221e
Reject anchored GPT creative shells
aram356 Aug 7, 2026
eb9e27f
Measure auction projection bytes from own data
aram356 Aug 7, 2026
859b6aa
Prepare the transactional GPT integration
aram356 Aug 7, 2026
8a0812e
Share the layered GPT script guard
aram356 Aug 7, 2026
a971842
Wire attributable GPT empty fallback
aram356 Aug 7, 2026
3b5cf81
Measure canonical auction projection bytes
aram356 Aug 7, 2026
3ba8b30
Harden GPT slot reconciliation races
aram356 Aug 7, 2026
ed44185
Bound shared auction registration graphs
aram356 Aug 7, 2026
4459017
Retain failed GPT reconciliation identities
aram356 Aug 7, 2026
c597c37
Harden Task 15 validation intrinsics
aram356 Aug 7, 2026
4f242d3
Classify shared DAG budget overflow
aram356 Aug 7, 2026
679671f
Publish GPT winners transactionally
aram356 Aug 7, 2026
d8f98b0
Revalidate GPT winner publication ownership
aram356 Aug 7, 2026
615352f
Latch GPT publication to physical slot
aram356 Aug 7, 2026
f3984e5
Harden exact-key validation helpers
aram356 Aug 7, 2026
87144b6
Remove ambient validation predicates
aram356 Aug 7, 2026
3e02edc
Stamp the external Prebid artifact
aram356 Aug 7, 2026
b9abc2e
Harden external Prebid artifact binding
aram356 Aug 7, 2026
fa5eccc
Retire artifacts with GPT slot ownership
aram356 Aug 7, 2026
f7e2dc0
Prepare the transactional Prebid module
aram356 Aug 7, 2026
a1f0f00
Publish Prebid bids transactionally
aram356 Aug 7, 2026
32c8b8a
Observe publisher GPT calls transactionally
aram356 Aug 7, 2026
7afa7b9
Scope Prebid queries to event callbacks
aram356 Aug 7, 2026
fd09a6f
Tombstone unselected Prebid groups
aram356 Aug 7, 2026
665539e
Admit Trusted Server bids through Prebid
aram356 Aug 7, 2026
a7139e2
Coordinate Prebid winner selection
aram356 Aug 7, 2026
54ea2ef
Fail closed during Prebid winner selection
aram356 Aug 7, 2026
9489499
Complete GPT handoff startup integration
aram356 Aug 7, 2026
acbc221
Verify Prebid admission against the real artifact
aram356 Aug 7, 2026
5da081a
Fix Prebid contract test command
aram356 Aug 7, 2026
936bf5c
Pin the Prebid response query contract
aram356 Aug 7, 2026
ec6eb5b
Activate Prebid listeners transactionally
aram356 Aug 7, 2026
494e183
Release Prebid bidder registrations explicitly
aram356 Aug 7, 2026
ce459b7
Bridge Prebid startup into runtime ownership
aram356 Aug 7, 2026
6c182bc
Arm Prebid selection before bidder startup
aram356 Aug 8, 2026
9153a68
Wire Prebid publication into browser composition
aram356 Aug 8, 2026
e1aa8b7
Establish creative integration ownership
aram356 Aug 8, 2026
f71f480
Own the creative guard lifecycle
aram356 Aug 8, 2026
14572b2
Allow clean creative guard reactivation
aram356 Aug 8, 2026
26025df
Harden GPT publisher handoff ownership
aram356 Aug 8, 2026
cc47b15
Complete browser integration lifecycle wiring
aram356 Aug 8, 2026
e82f3e7
Add bounded kernel diagnostics transport
aram356 Aug 8, 2026
e49b061
Close GPT cleanup race windows
aram356 Aug 8, 2026
226a08f
Add bounded render trace diagnostics
aram356 Aug 8, 2026
21f5004
Fix render trace isolation test typing
aram356 Aug 8, 2026
f4814a5
Publish terminal render diagnostics
aram356 Aug 8, 2026
2184738
Wire private runtime diagnostics
aram356 Aug 8, 2026
4da3000
Bound GPT diagnostics notifications
aram356 Aug 8, 2026
40c4696
Harden publisher GPT call provenance
aram356 Aug 8, 2026
fac4c50
Format GPT diagnostics notifications
aram356 Aug 8, 2026
899e08e
Add bounded GPT diagnostics fact capture
aram356 Aug 8, 2026
f602d6b
Commit publisher GPT intent transactionally
aram356 Aug 8, 2026
b555d42
Name and complete ts_console request gates
aram356 Aug 8, 2026
03d8561
Rebuild bounded GPT diagnostics
aram356 Aug 8, 2026
8176584
Move diagnostics session state to the server
aram356 Aug 8, 2026
f91f9d8
Complete runtime render trace diagnostics
aram356 Aug 8, 2026
328f5cd
Prepare remaining integration lifecycles
aram356 Aug 8, 2026
079f07f
Compose remaining integration runtimes
aram356 Aug 8, 2026
cd13e23
Build the Prebid refresh policy boundary
aram356 Aug 8, 2026
548045d
Prune render trace state with navigation ownership
aram356 Aug 8, 2026
8d3bb4d
Satisfy strict consent timer initialization
aram356 Aug 8, 2026
4dbdd9c
Use string-form Cargo aliases so nested worktrees do not break them (…
aram356 Aug 7, 2026
38897a3
Compose the Prebid refresh policy
aram356 Aug 8, 2026
fc27df9
Harden synthetic Prebid refresh routing
aram356 Aug 8, 2026
6e0c068
Test synthetic Prebid refresh boundaries
aram356 Aug 8, 2026
be5a7a2
Format Prebid refresh composition
aram356 Aug 8, 2026
753933e
Require CORS for cache creative fetches
aram356 Aug 8, 2026
1c2a454
Enforce Axum APS proxy transport deadlines
aram356 Aug 8, 2026
f1a8ad8
Test APS deadline at the transport boundary
aram356 Aug 8, 2026
e9358f5
Settle failed Prebid publications
aram356 Aug 8, 2026
517c78f
Test hostile Prebid failure settlement
aram356 Aug 8, 2026
faec1fc
Route GPT diagnostics through the kernel bus
aram356 Aug 8, 2026
55341cf
Document TSJS manifest errors
aram356 Aug 8, 2026
624f270
Format resilient TSJS modules
aram356 Aug 8, 2026
45de84d
Fix duplicate Prebid artifact equality
aram356 Aug 8, 2026
5c124c5
Harden creative boot and click ownership
aram356 Aug 8, 2026
eec0b99
Isolate creative lifecycle ownership
aram356 Aug 8, 2026
5f7d37a
Restore Testlight queue push parity
aram356 Aug 8, 2026
11aefe9
Harden GPT diagnostics fact ownership
aram356 Aug 8, 2026
6f26c2f
Cancel owned GPT diagnostics frames
aram356 Aug 8, 2026
7469a51
Clean diagnostics directives through server transport
aram356 Aug 8, 2026
e2b2900
Enrich render trace from safe GPT facts
aram356 Aug 8, 2026
3ba07ff
Latch first GPT render trace terminal fact
aram356 Aug 8, 2026
0e30fd3
Close the maximal runtime ownership gate
aram356 Aug 8, 2026
14ae7ae
Wire GPT facts into render diagnostics
aram356 Aug 8, 2026
747a630
Test GPT fact identity and timing
aram356 Aug 8, 2026
a1692a0
Format GPT diagnostics resilience changes
aram356 Aug 8, 2026
b79b4fc
Preserve publisher beacon replacements
aram356 Aug 8, 2026
86f8aa7
Reconcile GPT-first render trace terminals
aram356 Aug 8, 2026
1b12556
Isolate Lockr cleanup failures
aram356 Aug 8, 2026
ccdea45
Keep render trace counts aligned with current slots
aram356 Aug 8, 2026
372a570
Capture GPT subscriber membership at commit
aram356 Aug 8, 2026
8cf810c
Exercise maximal runtime failure isolation
aram356 Aug 8, 2026
6eb445c
Switch production to the resilient TSJS runtime
aram356 Aug 8, 2026
ad9d90e
Test hard-cutover browser lifecycle races
aram356 Aug 8, 2026
9f3278d
Fix hard-cutover browser boot races
aram356 Aug 8, 2026
8486a47
test(tsjs): add protected real-GAM attestation
aram356 Aug 8, 2026
618417c
Finalize APS TSJS load-time architecture
aram356 Aug 8, 2026
60d9d91
refactor(tsjs): enforce hard cutover
aram356 Aug 8, 2026
902e115
Harden TSJS cutover boundaries
aram356 Aug 8, 2026
d3ad7f1
docs(tsjs): make diagnostics ingress core-only
aram356 Aug 9, 2026
90d1201
Align the APS TSJS implementation plan
aram356 Aug 9, 2026
4f3cb30
Make diagnostics ingress core-only
aram356 Aug 11, 2026
f84142f
Prepare the remaining integration modules
aram356 Aug 11, 2026
74ba187
docs: define role-correct TSJS bundle budgets
aram356 Aug 12, 2026
6c5affe
Align the plan with role-correct TSJS gates
aram356 Aug 12, 2026
e12d224
Split TSJS around the protected first display
aram356 Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
56 changes: 31 additions & 25 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,60 @@
# default-members = [fastly] — required so Viceroy can locate the binary via `cargo run --bin`.
# The aliases below are grouped by adapter; each targets its adapter with the
# correct toolchain (build / check / test / clippy).
#
# Aliases use string form, not array form: in a worktree nested inside the
# repo (e.g. .claude/worktrees/*) Cargo discovers this file twice — the
# worktree's copy and the parent checkout's — and merges array values by
# concatenation, doubling every token ("check ... check ...").
# String values are overridden by the deeper config instead of merged.

[alias]
# Generic: native test with an explicit host target.
test_details = ["test", "--target", "aarch64-apple-darwin"]
test_details = "test --target aarch64-apple-darwin"

# --- Fastly adapter (wasm32-wasip1, run via Viceroy) ---
# Whitelist the wasm-buildable crates (the Fastly adapter + the shared crates it
# builds/tests on wasm) rather than blacklisting every native crate — so adding a
# native crate needs no change here. Axum (native), Cloudflare
# (wasm32-unknown-unknown), Spin, the CLI (native), and integration-tests
# (native) are simply not listed.
build-fastly = ["build", "-p", "trusted-server-core", "-p", "trusted-server-adapter-fastly", "-p", "trusted-server-js", "-p", "trusted-server-openrtb", "--target", "wasm32-wasip1"]
check-fastly = ["check", "-p", "trusted-server-core", "-p", "trusted-server-adapter-fastly", "-p", "trusted-server-js", "-p", "trusted-server-openrtb", "--target", "wasm32-wasip1"]
clippy-fastly = ["clippy", "-p", "trusted-server-core", "-p", "trusted-server-adapter-fastly", "-p", "trusted-server-js", "-p", "trusted-server-openrtb", "--all-targets", "--all-features", "--target", "wasm32-wasip1", "--", "-D", "warnings"]
test-fastly = ["test", "-p", "trusted-server-core", "-p", "trusted-server-adapter-fastly", "-p", "trusted-server-js", "-p", "trusted-server-openrtb", "--target", "wasm32-wasip1"]
build-fastly = "build -p trusted-server-core -p trusted-server-adapter-fastly -p trusted-server-js -p trusted-server-openrtb --target wasm32-wasip1"
check-fastly = "check -p trusted-server-core -p trusted-server-adapter-fastly -p trusted-server-js -p trusted-server-openrtb --target wasm32-wasip1"
clippy-fastly = "clippy -p trusted-server-core -p trusted-server-adapter-fastly -p trusted-server-js -p trusted-server-openrtb --all-targets --all-features --target wasm32-wasip1 -- -D warnings"
test-fastly = "test -p trusted-server-core -p trusted-server-adapter-fastly -p trusted-server-js -p trusted-server-openrtb --target wasm32-wasip1"

# --- Axum adapter (native dev server) ---
build-axum = ["build", "-p", "trusted-server-adapter-axum"]
check-axum = ["check", "-p", "trusted-server-adapter-axum"]
clippy-axum = ["clippy", "-p", "trusted-server-adapter-axum", "--all-targets", "--all-features", "--", "-D", "warnings"]
test-axum = ["test", "-p", "trusted-server-adapter-axum"]
build-axum = "build -p trusted-server-adapter-axum"
check-axum = "check -p trusted-server-adapter-axum"
clippy-axum = "clippy -p trusted-server-adapter-axum --all-targets --all-features -- -D warnings"
test-axum = "test -p trusted-server-adapter-axum"

# --- Cloudflare adapter (native host + wasm32-unknown-unknown) ---
# Build/check target the WASM runtime (requires the `cloudflare` feature);
# tests run on the native host; clippy covers both native test code and the
# production WASM feature.
build-cloudflare = ["build", "-p", "trusted-server-adapter-cloudflare", "--target", "wasm32-unknown-unknown", "--features", "cloudflare"]
check-cloudflare = ["check", "-p", "trusted-server-adapter-cloudflare", "--target", "wasm32-unknown-unknown", "--features", "cloudflare"]
build-cloudflare = "build -p trusted-server-adapter-cloudflare --target wasm32-unknown-unknown --features cloudflare"
check-cloudflare = "check -p trusted-server-adapter-cloudflare --target wasm32-unknown-unknown --features cloudflare"
# No --all-features: the `cloudflare` feature has a compile_error! guard on
# non-wasm32 targets.
clippy-cloudflare = ["clippy", "-p", "trusted-server-adapter-cloudflare", "--all-targets", "--", "-D", "warnings"]
clippy-cloudflare-wasm = ["clippy", "-p", "trusted-server-adapter-cloudflare", "--target", "wasm32-unknown-unknown", "--features", "cloudflare", "--lib", "--", "-D", "warnings"]
test-cloudflare = ["test", "-p", "trusted-server-adapter-cloudflare"]
clippy-cloudflare = "clippy -p trusted-server-adapter-cloudflare --all-targets -- -D warnings"
clippy-cloudflare-wasm = "clippy -p trusted-server-adapter-cloudflare --target wasm32-unknown-unknown --features cloudflare --lib -- -D warnings"
test-cloudflare = "test -p trusted-server-adapter-cloudflare"

# --- Spin adapter (native host tests + wasm32-wasip1 target) ---
check-spin = ["check", "-p", "trusted-server-adapter-spin", "--target", "wasm32-wasip1", "--features", "spin"]
clippy-spin-native = ["clippy", "-p", "trusted-server-adapter-spin", "--all-targets", "--", "-D", "warnings"]
clippy-spin-wasm = ["clippy", "-p", "trusted-server-adapter-spin", "--target", "wasm32-wasip1", "--features", "spin", "--lib", "--", "-D", "warnings"]
test-spin = ["test", "-p", "trusted-server-adapter-spin"]
check-spin = "check -p trusted-server-adapter-spin --target wasm32-wasip1 --features spin"
clippy-spin-native = "clippy -p trusted-server-adapter-spin --all-targets -- -D warnings"
clippy-spin-wasm = "clippy -p trusted-server-adapter-spin --target wasm32-wasip1 --features spin --lib -- -D warnings"
test-spin = "test -p trusted-server-adapter-spin"

# --- ts operator CLI (native host; install uses the current host platform) ---
install-cli = ["install", "--path", "crates/trusted-server-cli", "--bin", "ts", "--locked", "--force"]
build_cli_linux = ["build", "--package", "trusted-server-cli", "--target", "x86_64-unknown-linux-gnu"]
build_cli_macos = ["build", "--package", "trusted-server-cli", "--target", "aarch64-apple-darwin"]
run_cli_linux = ["run", "--package", "trusted-server-cli", "--target", "x86_64-unknown-linux-gnu", "--"]
run_cli_macos = ["run", "--package", "trusted-server-cli", "--target", "aarch64-apple-darwin", "--"]
test_cli_linux = ["test", "--package", "trusted-server-cli", "--target", "x86_64-unknown-linux-gnu"]
test_cli_macos = ["test", "--package", "trusted-server-cli", "--target", "aarch64-apple-darwin"]
install-cli = "install --path crates/trusted-server-cli --bin ts --locked --force"
build_cli_linux = "build --package trusted-server-cli --target x86_64-unknown-linux-gnu"
build_cli_macos = "build --package trusted-server-cli --target aarch64-apple-darwin"
run_cli_linux = "run --package trusted-server-cli --target x86_64-unknown-linux-gnu --"
run_cli_macos = "run --package trusted-server-cli --target aarch64-apple-darwin --"
test_cli_linux = "test --package trusted-server-cli --target x86_64-unknown-linux-gnu"
test_cli_macos = "test --package trusted-server-cli --target aarch64-apple-darwin"

# When a wasm binary IS built, run it under Viceroy.
[target.'cfg(all(target_arch = "wasm32"))']
Expand Down
118 changes: 118 additions & 0 deletions .github/workflows/aps-real-gam.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: "APS real-GAM attestation"
run-name: >-
APS real-GAM / ${{ inputs.evidence_id }} / ${{ inputs.release_id }}

permissions:
contents: read

on:
workflow_dispatch:
inputs:
release_id:
description: Exact TSJS release id deployed to the protected test network
required: true
type: string
evidence_id:
description: Unique cutover evidence identifier
required: true
type: string
previous_artifact_id:
description: Immutable artifact identifier used for rollback
required: true
type: string

jobs:
attest:
name: Chromium, Firefox, and WebKit attestation
runs-on: ubuntu-latest
timeout-minutes: 90
environment: aps-real-gam
env:
TS_REAL_GAM_PAGE_URL: ${{ secrets.TS_REAL_GAM_PAGE_URL }}
TS_REAL_GAM_AUTH_HEADER: ${{ secrets.TS_REAL_GAM_AUTH_HEADER }}
TS_REAL_GAM_EXPECTED_RELEASE_ID: ${{ vars.TS_REAL_GAM_EXPECTED_RELEASE_ID }}
steps:
- uses: actions/checkout@v4

- name: Validate protected inputs and release binding
env:
DISPATCH_RELEASE_ID: ${{ inputs.release_id }}
run: |
test -n "$TS_REAL_GAM_PAGE_URL"
test -n "$TS_REAL_GAM_AUTH_HEADER"
test -n "$TS_REAL_GAM_EXPECTED_RELEASE_ID"
test -n "$DISPATCH_RELEASE_ID"
test "$DISPATCH_RELEASE_ID" = "$TS_REAL_GAM_EXPECTED_RELEASE_ID"
test -n "${{ inputs.evidence_id }}"
test -n "${{ inputs.previous_artifact_id }}"

- name: Read Node.js version
id: node-version
run: echo "version=$(awk '$1 == \"nodejs\" { print $2 }' .tool-versions)" >> "$GITHUB_OUTPUT"

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ steps.node-version.outputs.version }}
cache: npm
cache-dependency-path: crates/trusted-server-integration-tests/browser/package-lock.json

- name: Install isolated browser-test dependencies
working-directory: crates/trusted-server-integration-tests/browser
run: npm ci

- name: Install all required browsers
working-directory: crates/trusted-server-integration-tests/browser
run: npx playwright install --with-deps chromium firefox webkit

- name: Run protected real-GAM contract
id: real-gam
working-directory: crates/trusted-server-integration-tests/browser
run: >-
npm exec -- playwright test
--config=playwright.real-gam.config.ts
tests/shared/aps-real-gam.spec.ts
--project=chromium --project=firefox --project=webkit

- name: Write release attestation
if: always()
env:
ATTESTATION_EVIDENCE_ID: ${{ inputs.evidence_id }}
ATTESTATION_RELEASE_ID: ${{ inputs.release_id }}
ATTESTATION_PREVIOUS_ARTIFACT_ID: ${{ inputs.previous_artifact_id }}
ATTESTATION_TEST_OUTCOME: ${{ steps.real-gam.outcome }}
run: >-
node -e 'const fs=require("node:fs");
const path="crates/trusted-server-integration-tests/browser/real-gam-evidence/attestation-v1.json";
fs.mkdirSync(require("node:path").dirname(path),{recursive:true});
fs.writeFileSync(path,JSON.stringify({schemaVersion:1,evidenceId:process.env.ATTESTATION_EVIDENCE_ID,
releaseId:process.env.ATTESTATION_RELEASE_ID,previousArtifactId:process.env.ATTESTATION_PREVIOUS_ARTIFACT_ID,
commitSha:process.env.GITHUB_SHA,runId:process.env.GITHUB_RUN_ID,
conclusion:process.env.ATTESTATION_TEST_OUTCOME},null,2)+"\n",{mode:384});'

- name: Scrub browser evidence before upload
if: always()
env:
REAL_GAM_TEST_OUTCOME: ${{ steps.real-gam.outcome }}
working-directory: crates/trusted-server-integration-tests/browser
run: >-
node -e 'const fs=require("node:fs"),path=require("node:path");
const roots=["real-gam-evidence","playwright-report","test-results"];
const forbiddenExt=new Set([".har",".zip",".webm"]), secrets=[process.env.TS_REAL_GAM_PAGE_URL,process.env.TS_REAL_GAM_AUTH_HEADER].filter(Boolean);
const files=[]; const walk=p=>{if(!fs.existsSync(p))return; for(const e of fs.readdirSync(p,{withFileTypes:true})){const q=path.join(p,e.name); e.isDirectory()?walk(q):files.push(q)}}; roots.forEach(walk);
for(const file of files){if(forbiddenExt.has(path.extname(file)))throw Error("native capture forbidden: "+path.extname(file)); const body=fs.readFileSync(file); for(const secret of secrets){if(body.includes(Buffer.from(secret)))throw Error("protected value found in browser evidence")}}
const traces=files.filter(file=>file.endsWith("sanitized-trace-v1.json"));
for(const file of traces){const text=fs.readFileSync(file,"utf8"); if(/"(?:accountId|aaxResponse|adm|authorization|creativeBody|descriptor|lifecycleTicket|nonce|postData|requestHeaders|responseBody|responseHeaders)"\s*:/.test(text)||text.includes("<script")||text.includes("<!doctype"))throw Error("unsafe field or body found in sanitized evidence")}
if(process.env.REAL_GAM_TEST_OUTCOME==="success"&&traces.length!==60)throw Error("successful three-browser run must emit 60 sanitized case traces");'

- name: Upload real-GAM evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: aps-real-gam-${{ github.run_id }}
path: |
crates/trusted-server-integration-tests/browser/real-gam-evidence/
crates/trusted-server-integration-tests/browser/playwright-report/
crates/trusted-server-integration-tests/browser/test-results/
if-no-files-found: error
retention-days: 30
133 changes: 132 additions & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
name: "Integration Tests"
run-name: >-
Integration Tests / ${{ inputs.evidence_id || format('PR {0}', github.event.pull_request.number) }}

permissions:
contents: read
Expand All @@ -9,6 +11,11 @@ on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
evidence_id:
description: Unique identifier used to bind this run to an evidence artifact
required: true
type: string

env:
ORIGIN_PORT: 8888
Expand Down Expand Up @@ -152,10 +159,58 @@ jobs:
VICEROY_CONFIG_PATH: ${{ env.ARTIFACTS_DIR }}/configs/viceroy.toml
RUST_LOG: info

aps-runner-proxy:
name: APS runner proxy (${{ matrix.runtime }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
runtime: [axum, fastly, cloudflare, spin]
steps:
- uses: actions/checkout@v4

- name: Set up APS proxy test environment
id: shared-setup
uses: ./.github/actions/setup-integration-test-env
with:
origin-port: ${{ env.ORIGIN_PORT }}
install-viceroy: ${{ matrix.runtime == 'fastly' && 'true' || 'false' }}
build-wasm: "false"
build-axum: "false"
build-test-images: "false"
build-cloudflare: "false"

- name: Add Cloudflare wasm target
if: matrix.runtime == 'cloudflare'
run: rustup target add wasm32-unknown-unknown

- name: Set up Node.js for Wrangler
if: matrix.runtime == 'cloudflare'
uses: actions/setup-node@v4
with:
node-version: ${{ steps.shared-setup.outputs.node-version }}

- name: Install Wrangler
if: matrix.runtime == 'cloudflare'
run: npm install -g wrangler@4.64.0

- name: Install Spin
if: matrix.runtime == 'spin'
uses: fermyon/actions/spin/setup@v1
with:
version: "4.0.2"

- name: Run actual-adapter APS runner-proxy corpus
run: ./scripts/integration-tests-aps-runner-proxy.sh --runtime ${{ matrix.runtime }}
env:
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
RUST_LOG: info

browser-tests:
name: browser integration tests
needs: prepare-artifacts
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -244,3 +299,79 @@ jobs:
name: playwright-traces
path: crates/trusted-server-integration-tests/browser/test-results/
retention-days: 7

- name: Record TSJS pre-change performance evidence
if: github.event_name == 'workflow_dispatch'
working-directory: crates/trusted-server-integration-tests/browser
env:
WASM_BINARY_PATH: ${{ env.WASM_ARTIFACT_PATH }}
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
VICEROY_CONFIG_PATH: ${{ env.ARTIFACTS_DIR }}/configs/viceroy.toml
TEST_FRAMEWORK: nextjs
TSJS_PERF_MODE: baseline
TSJS_PERF_OUTPUT: crates/trusted-server-js/lib/test/fixtures/performance/aps-tsjs-prechange.json
TSJS_PERF_MACHINE_CLASS: github-hosted:ubuntu-24.04
TSJS_EVIDENCE_ID: ${{ inputs.evidence_id }}
run: >-
npm exec -- playwright test
tests/shared/tsjs-performance.spec.ts
--project=chromium

- name: Upload TSJS pre-change performance evidence
if: github.event_name == 'workflow_dispatch' && always()
uses: actions/upload-artifact@v4
with:
name: tsjs-performance-${{ inputs.evidence_id }}
path: crates/trusted-server-js/lib/test/fixtures/performance/aps-tsjs-prechange.json
if-no-files-found: error
retention-days: 30

browser-tests-aps-tsjs-conformance:
name: browser integration tests (APS/TSJS conformance)
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- name: Set up APS/TSJS browser test runtime
id: shared-setup
uses: ./.github/actions/setup-integration-test-env
with:
origin-port: ${{ env.ORIGIN_PORT }}
install-viceroy: "true"
build-wasm: "false"
build-axum: "false"
build-test-images: "false"
build-cloudflare: "false"

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ steps.shared-setup.outputs.node-version }}
cache: npm
cache-dependency-path: |
crates/trusted-server-integration-tests/browser/package-lock.json
crates/trusted-server-js/lib/package-lock.json

- name: Run focused APS/TSJS three-browser conformance matrix
env:
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
TS_BROWSER_FRAMEWORKS: nextjs
TS_BROWSER_PROJECTS: chromium,firefox,webkit
run: >-
./scripts/integration-tests-browser.sh
tests/shared/aps-renderer.spec.ts
tests/shared/aps-puc-lifecycle.spec.ts
tests/shared/tsjs-runtime.spec.ts
tests/shared/creative-sandbox.spec.ts
tests/nextjs/gpt-diagnostics.spec.ts
tests/nextjs/navigation.spec.ts
--project=chromium --project=firefox --project=webkit

- name: Upload APS/TSJS Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-aps-tsjs-conformance
path: crates/trusted-server-integration-tests/browser/playwright-report/
retention-days: 7
21 changes: 21 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,5 +247,26 @@ jobs:
- name: Build bundle
run: npm run build

- name: Enforce bundle budgets
run: npm run check:bundle

- name: Typecheck full TSJS package
run: npm run typecheck

- name: Lint full TSJS package
run: npm run lint

- name: Verify generated APS renderer contract
run: npm run check:aps-contract

- name: Enforce hard-cutover architecture
run: npm run check:architecture

- name: Run embedded APS renderer contract
run: node --test test/contract/aps-renderer-es5.test.mjs

- name: Verify rc/july adoption manifest
run: node --test test/contract/rc-july-adoption.test.mjs

- name: Run unit tests
run: npm test -- --run
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fastly 15.1.0
rust 1.95.0
nodejs 24.12.0
viceroy 0.17.0
viceroy 0.19.0
wasmtime 44.0.1
Loading