Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions REPOSITORY_LIFECYCLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ revocation, release drift, an authority failure, or missing evidence produces
the same state. The validator never restores an older admission or replaces
the state with Beta, Experimental, or Early access.

The signed ledger currently has no active admissions. These are the derived
states:
The signed ledger currently has one active admission, for `flow`. The other
six targets have none. Product-wide Production requires all seven. These are
the derived states:

| Target | Current state | Role |
|------------|-----------|------|
| `openadapt` | **Not actively admitted** | `OpenAdapt` launcher/meta-package and unified CLI |
| `flow` | **Not actively admitted** | `openadapt-flow` compiler and governed runtime |
| `flow` | **Production** | `openadapt-flow` compiler and governed runtime |
| `cloud` | **Not actively admitted** | Proprietary control plane and hosted execution surface |
| `desktop` | **Not actively admitted** | Desktop recording, qualification, execution, evidence, and repair cockpit |
| `capture` | **Not actively admitted** | Native screen, input, timing, window, and media capture |
Expand Down
15 changes: 10 additions & 5 deletions scripts/validate_production_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@
}


def is_product_production(active: Mapping[str, str]) -> bool:
"""True only when every one of the seven targets has an active admission."""

return set(active) == set(EXPECTED_TARGETS)


class LifecycleError(ValueError):
"""The lifecycle state is not supported by its evidence."""

Expand Down Expand Up @@ -1906,11 +1912,10 @@ def validate(
f"admission {target_id} release sequence is not continuous"
)
seen.append(sequence)
# remote-safe-synthetic is a real package admission. It is not
# seven-target Production and it does not flip MockMed
# production_acceptance.
if admission["evidence_class"] != "remote-safe-synthetic":
active[target_id] = admission_id
# remote-safe-synthetic is a real package admission for this
# target. One row is not seven-target Production. It does not
# flip MockMed production_acceptance.
active[target_id] = admission_id
continue
admission = _closed(
item,
Expand Down
33 changes: 32 additions & 1 deletion tests/test_production_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,38 @@ def test_published_policy_is_accepted(self) -> None:
# The Flow 1.34.0 row is issued 2026-09-02T18:24:25Z. NOW is the
# retained v1 fixture clock and is before that instant.
published_now = datetime(2026, 9, 2, 19, 0, 0, tzinfo=timezone.utc)
self.assertEqual(lifecycle.validate_files(ROOT, now=published_now), {})
active = lifecycle.validate_files(ROOT, now=published_now)
release = json.loads(
(
ROOT
/ "production-evidence/objects/sha256/79/"
"790122a25c87e456c6e45d25ebf5cd029b21b8511265b062fd9129b74aa1dd82"
".qualification-release.json"
).read_text(encoding="utf-8")
)
self.assertEqual(release["evidence_class"], "remote-safe-synthetic")
self.assertEqual(release["target"], "flow")
self.assertEqual(active, {"flow": release["admission_id_sha256"]})
self.assertEqual(len(lifecycle.EXPECTED_TARGETS), 7)
self.assertFalse(lifecycle.is_product_production(active))

def test_synthetic_flow_release_is_one_active_target_not_product_production(
self,
) -> None:
published_now = datetime(2026, 9, 2, 19, 0, 0, tzinfo=timezone.utc)
active = lifecycle.validate_files(ROOT, now=published_now)
self.assertEqual(len(active), 1)
self.assertIn("flow", active)
self.assertEqual(
set(lifecycle.EXPECTED_TARGETS) - set(active),
{"agent", "capture", "cloud", "desktop", "docs", "openadapt"},
)
self.assertFalse(lifecycle.is_product_production(active))
seven = {
target_id: f"admission:{target_id}"
for target_id in lifecycle.EXPECTED_TARGETS
}
self.assertTrue(lifecycle.is_product_production(seven))

def test_check_profile_accepts_the_published_repository(self) -> None:
completed = subprocess.run(
Expand Down