Files
devplacepy/tests/api/admin/services/acceptance.py
T
retoorandClaude Opus 5 7e37122f9f Converge every account onto every policy agreement it has not declined
An instance kept production-identical for extended manual testing is
otherwise taxed forever by its own safety controls: five consents, a
versioned terms gate on every mutating request, and every account
predating the trust and safety commit reading terms_version NULL because
init_db deliberately never backfills it. AcceptanceService grants each
agreement to each account that has not declined it, so the instance stays
production byte for byte while nobody clicks the same dialog again. It is
opt-in, dry run by default, and one switch per agreement type.

The application is not allowed to know it exists. One registration line
in main.py is the only import anywhere, there is no route, schema,
template, Devii tool or environment flag, and a unit test greps the tree
and fails the suite if a second importer appears. The decline register
needs no storage: the ledger is append-only in effect, the service only
ever grants, so any withdrawn row was written by a human and that pair is
never touched again. No provenance column, nothing to observe.

Satisfaction is the gate's own expression, never a proxy, which is why
the ordering is created_at then id exactly as consent_state selects, and
why the live-account clauses are built with has_column: init_db ensures
terms_version and deletion_requested_at but not is_active, so a hardcoded
reference raises no such column on an instance where nobody was ever
suspended. Every write is one conditional statement decided on the real
rowcount, proven with sixteen processes racing one account to exactly one
ledger row and one audit row. The two existing audit keys carry it, with
actor kind service, because a service that silently mutated consent state
would be the worst possible exception to the append-only rule.

lensfl.md is the source brief accept.md records the design against.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 00:17:47 +02:00

90 lines
2.9 KiB
Python

# retoor <retoor@molodetz.nl>
import requests
from tests.conftest import BASE_URL
from devplacepy.database import (
clear_settings_cache,
get_setting,
get_table,
refresh_snapshot,
set_setting,
)
from devplacepy.services.acceptance.agreements import AGREEMENTS, setting_key
JSON = {"Accept": "application/json"}
SERVICE_URL = f"{BASE_URL}/admin/services/acceptance"
def _admin(seeded_db):
refresh_snapshot()
key = get_table("users").find_one(username="alice_test")["api_key"]
session = requests.Session()
session.headers.update({"X-API-KEY": key, **JSON})
return session
def test_the_service_is_listed_and_stopped_by_default(seeded_db):
admin = _admin(seeded_db)
r = admin.get(f"{BASE_URL}/admin/services/data")
assert r.status_code == 200, r.text[:300]
entry = next(
item for item in r.json()["services"] if item["name"] == "acceptance"
)
assert entry["enabled"] is False
assert entry["status"] == "stopped"
assert entry["title"] == "Acceptance convergence"
def test_the_detail_page_renders_one_field_per_agreement(seeded_db):
admin = _admin(seeded_db)
r = admin.get(f"{SERVICE_URL}/data")
assert r.status_code == 200, r.text[:300]
fields = {field["key"]: field for field in r.json()["service"]["fields"]}
for agreement in AGREEMENTS:
field = fields[setting_key(agreement.kind)]
assert field["type"] == "bool"
assert field["value"] == "0"
assert field["group"] == "Agreements"
assert fields["acceptance_dry_run"]["value"] == "1"
assert fields["service_acceptance_enabled"]["value"] == "0"
def test_the_detail_page_renders_html_for_an_admin(seeded_db):
admin = _admin(seeded_db)
r = requests.get(SERVICE_URL, headers={"X-API-KEY": admin.headers["X-API-KEY"]})
assert r.status_code == 200
assert "Acceptance convergence" in r.text
def test_an_admin_saves_an_agreement_toggle(seeded_db):
admin = _admin(seeded_db)
key = setting_key("container_credentials")
original = get_setting(key, "0")
try:
r = admin.post(f"{SERVICE_URL}/config", data={key: "1"})
assert r.status_code == 200, r.text[:300]
assert r.json().get("ok") is True
refresh_snapshot()
clear_settings_cache()
assert get_setting(key, "0") == "1"
finally:
set_setting(key, original)
def test_an_invalid_batch_size_is_refused(seeded_db):
admin = _admin(seeded_db)
r = admin.post(f"{SERVICE_URL}/config", data={"acceptance_batch_size": "banana"})
assert r.status_code == 400
assert r.json()["errors"]["acceptance_batch_size"]
def test_a_guest_cannot_read_the_service(app_server):
r = requests.get(f"{SERVICE_URL}/data", headers=JSON, allow_redirects=False)
assert r.status_code in (302, 303, 401, 403)
def test_the_master_switch_stays_off_for_the_suite(seeded_db):
refresh_snapshot()
clear_settings_cache()
assert get_setting("service_acceptance_enabled", "0") != "1"