Skip to content

Add acceptance foundations: private origins, cross-platform CI and the Acme fixture - #15

Merged
ancongui merged 40 commits into
mainfrom
feat/acceptance-foundations
Oct 8, 2026
Merged

ancongui merged 40 commits into
mainfrom
feat/acceptance-foundations

Conversation

@ancongui

@ancongui ancongui commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Summary

S6-M0 foundations for end-to-end acceptance:

  • Private-origin policy (C8). firefly_weave.private_origins is the one loader every process uses for private egress and the per-purpose plain-text rules: WEAVE_PRIVATE_ORIGINS_FILE, entries {origin, purpose, networks, credentials}, one decision before every connection's first write, always-refused addresses after decoding IPv4-mapped, NAT64, 6to4 and Teredo forms, audit lines, "Development only" and "Legacy setting" labels, and the legacy-setting mapping.
  • Connector clients on C8. HTTP connector actions, HTTP profiles, machine-token endpoints and signed webhooks (http-connector, event-delivery) decide private reach through C8. HTTP profile connections (weave-http@2.0.0) accept http:// base URLs exactly like weave-http@1.0.0: public addresses as they are, private, loopback and CGNAT ones only through C8; machine-token endpoints stay HTTPS-only.
  • Plain HTTP is allowed and never silent (owner decision, 2026-10-07). The connection test answer carries encrypted: false for an http:// connection; weave connections create, read and test, and weave connector import-openapi --target builtin, print Not encrypted: requests to http://… travel in plain text. on standard error; Studio's connection form shows a "Not encrypted" notice next to the API address.
  • weave platform up --allow-private-origin ORIGIN (development only): records consent in platform.json before anything is written, creates weave-local-<id>-egress, writes one entry per purpose with credentials: bridge and networks set to exactly the egress subnet, and mounts a read-only copy into the API. A changed, loosened, linked or missing file stops every weave platform command; the docs give the recovery.
  • Cross-platform CI tier on macos-15 and windows-2022: Studio vitest, the @xplat Playwright subset (47 tests) and a portable Python subset. Linux jobs are pinned to ubuntu-24.04; the desktop Linux build keeps ubuntu-22.04.
  • Studio test portability. studio/tests/python-path.ts resolves the interpreter per operating system (CI fails instead of skipping), and the credential-store audit works on macOS, Linux and Windows and fails when the store is unavailable.
  • Acceptance harness skeleton. scripts/acceptance.py (prepare, up, run, collect, scan, down), evidence.schema.json and the canary scan (fails closed on unreadable directories), journeys.toml step enablement, versions.toml, the Acme API fixture, journey J0 with redacted failure output, and the quick-integration test moved from jsonplaceholder to the Acme fixture. A run fails when an enabled step has no passing test. The new Acceptance workflow runs the pr profile on ubuntu-24.04 with container egress blocked.
  • tests/unit/test_release_versions.py, and upgrades.md rows for alpha13 and alpha14.

C8 loader API (firefly_weave.private_origins)

  • Types and constants: Purpose (the ten C8 purposes), Credentials (none | loopback | bridge), PurposeRule(schemes, plaintext, connector, public_plaintext), PURPOSES, LEGACY_SETTINGS, ENV_FILE = "WEAVE_PRIVATE_ORIGINS_FILE", FORMAT = "weave/private-origins-v1", PLATFORM = "local-development", DEVELOPMENT_ONLY, LEGACY_SETTING, MAX_FILE_BYTES.
  • Errors: PrivateOriginsInvalid(ValueError) (the process must not start), PrivateOriginDenied(ValueError) with .reason.
  • Models: PrivateOrigin(origin, purpose, networks, credentials, source="file" | "legacy", setting=None, plaintext_networks=None) with .label; PrivateOrigins(entries, platform, file_sha256) with .empty(), .for_purpose(), .match(), .permits_plaintext(), .check(purpose, url, addresses, *, plaintext=None, sends_credentials=False, local=is_local_address), .with_entries(), .with_legacy(purposes, networks, *, setting, plaintext_networks=None).
  • Functions: canonical_origin, address, embedded_ipv4, always_denied, is_private, is_local_address, parse, read_file, render, load, install, active, installed.
  • firefly_weave.sdk.platform_origins (FILE, COMPOSE, CONTAINER_PATH, requested, prepare, verified, summary, …) is how other lanes add their own entries: read verified(state), call PrivateOrigins.with_entries, write render(...) and update file_sha256.

Behavior changes for the next release notes

  • No breaking change for connectors and webhooks reaching public addresses. HTTP connector actions (weave-http@1.0.0) and signed webhooks keep plain HTTP to public addresses, with or without credentials, and every existing check (allowlist, DNS pinning, peer check, redirect rules, caps). WEAVE_HTTP_PRIVATE_NETWORKS becomes a legacy setting mapped to the private-origin policy with a startup warning and the same reach; CGNAT addresses still need an explicit network entry, and 100.100.100.200 stays refused.
  • Requests to an approved development origin never follow redirects, and a connection to it is refused when the control-plane probe cannot tell whether the address is the platform's own.
  • No-code HTTP connections accept http:// base URLs and warn that traffic is not encrypted.
  • The connection test answer gains the encrypted field. CLIs and SDKs from 0.1.0a14 cannot read weave connections test answers for HTTP connections from an upgraded server: upgrade them together with the server (recorded in CHANGELOG.md).
  • Legacy private-network settings are parsed strictly at startup: a CIDR with host bits set, or more than 128 networks, now stops the API instead of failing requests at use time (recorded in CHANGELOG.md and docs/operations/configuration.md).

Testing

Verified locally (macOS, Python 3.13 locally; CI runs 3.12):

  • scripts/check.py (offline gate: source coverage, docs and docs site, ruff, mypy, unit and contract tests, both workers' gates, artifact checks): All requested checks passed. on the head commit.
  • Studio: type check, Prettier check, vitest (60 files, 666 tests), production build, and the mocked Playwright suite (915 passed; the real-platform suite skips without WEAVE_E2E_*).
  • HTTP egress integration tests (tests/integration/test_http_connector.py, tests/integration/connectors/test_plain_http_acme.py): 22 passed.
  • The portable Python subset that the cross-platform tier runs: 1,525 passed on macOS.
  • scripts/acceptance.py --profile pr against a real Docker platform on Colima, on the head commit: all six stages passed; J0's enabled steps passed or are partial only for checks owned by unmerged milestones; the quick-integration test passed against the Acme fixture; secret scan 0 hits; no resources left.

Proven only by CI on this PR:

  • The cross-platform tier on macos-15 and windows-2022 (Studio vitest, the @xplat subset, the portable Python subset), including the Windows interpreter path, the Windows cmdkey audit and Studio tests that used to skip silently on Windows.
  • The Acceptance workflow on ubuntu-24.04 with container egress blocked by iptables, the Secret Service audit through gnome-keyring, and a cold image cache (local runs were warm and did not block egress).
  • Documentation and the four Desktop installers targets.

Andres Contreras added 30 commits October 7, 2026 23:38
Andres Contreras added 10 commits October 8, 2026 04:31
 into feat/acceptance-foundations

# Conflicts:
#	studio/tests/schema-coverage.test.ts
…t IDs

pytest exports each running test's ID as PYTEST_CURRENT_TEST, and Windows
refuses an environment variable longer than 32,767 characters. The oversized
case put a 64 KiB document into its generated ID, so the cross-platform tier
errored on Windows at setup and teardown.
Collection now fails when a test's PYTEST_CURRENT_TEST assignment would exceed
the Windows limit, so a long generated ID fails on macOS and Linux too instead
of only on the Windows runner. The four tests whose oversized cases tripped it
get short explicit IDs.
…atform test

Create needs the connector version that the dialog's readiness check finds;
clicking while the check is still running only reports that Studio is still
checking and sends nothing. On the Linux CI runner the click landed inside
that window, so no POST /connections ever came and the test timed out.
…on preview

A test that failed before removing its platform left its credentials in
the system store, so the suite's audit failed a second time for the same
cause. Delete the bindings a failed test stored after it; the audit still
fails when a passing test leaves one behind.

The quick-integration test opened the YAML preview 5 seconds after
filling the builder, but the preview appears only once the test's freshly
started Studio host has analyzed the request, which the host allows 30
seconds. Wait for the preview to name the action first.
 into feat/acceptance-foundations

# Conflicts:
#	docs/contributing/source-inventory.toml
journeys.toml keyed step enablement by internal planning IDs. The table is
now [capabilities], and each entry names the product capability a step
waits for (acceptance-foundations, compose-operations, step-tests, and so
on), one for one with the old keys and with the same values. Requirements,
alternatives, skipped-step evidence, error messages and the acceptance
guide use the new names; unknown capability keys are refused, and the
harness comments no longer cite private planning documents.
@ancongui
ancongui merged commit 24e8f52 into main Oct 8, 2026
17 checks passed
@ancongui
ancongui deleted the feat/acceptance-foundations branch October 8, 2026 17:32
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.

1 participant