"""Static safety checks for the T-011 Sense Control API implementation.""" from __future__ import annotations import json import pathlib import re import unittest ROOT = pathlib.Path(__file__).resolve().parents[1] def text(relative: str) -> str: return (ROOT / relative).read_text(encoding="utf-8") def normalized(value: str) -> str: return re.sub(r"\s+", " ", value.lower()) class SenseControlImplementationTests(unittest.TestCase): def test_generated_server_covers_all_frozen_operations(self) -> None: generated = text("Sense/internal/controlapi/generated.gen.go") self.assertIn("Code generated by github.com/oapi-codegen/oapi-codegen/v2", generated) for operation in ( "ListDevices", "CreateDevice", "GetDevice", "UpdateDevice", "SetDeviceDesiredState", "BatchSetDeviceDesiredState", "GetOperation", ): self.assertIn(operation, generated) config = text("Sense/internal/controlapi/oapi-codegen.yaml") self.assertIn("std-http-server: true", config) self.assertIn("./internal/controlapi", text("init.ps1")) def test_control_api_is_feature_gated_to_postgres(self) -> None: config = text("Sense/internal/config/config.go") main = text("Sense/cmd/sense-api/main.go") self.assertIn('SENSE_CONTROL_API_ENABLED', config) self.assertIn('Control API requires SENSE_DB_DRIVER=postgres', config) self.assertIn('mux.Handle("/api/v1/", controlHandler)', main) self.assertNotIn('mux.Handle("/api/v1/"', text("Sense/internal/store/sqlite.go")) def test_static_authentication_stores_only_digests(self) -> None: source = text("Sense/internal/auth/auth.go") example = json.loads(text("Sense/api/control-auth.example.json")) self.assertIn("subtle.ConstantTimeCompare", source) self.assertIn("sha256.Sum256([]byte(token))", source) self.assertNotIn('json:"token"', source) for principal in example["principals"]: self.assertRegex(principal["token_sha256"], r"^[0-9a-f]{64}$") self.assertNotIn("token", principal.keys() - {"token_sha256"}) def test_postgres_receipts_are_hashed_durable_and_at_least_24_hours(self) -> None: migration = normalized(text("deploy/postgres/008_control_api.sql")) implementation = text("Sense/internal/store/control_postgres.go") self.assertIn("create table if not exists sense.control_idempotency_receipts", migration) self.assertIn("scope_hash bytea primary key", migration) self.assertIn("expires_at >= created_at + interval '24 hours'", migration) self.assertNotIn("idempotency_key", migration) self.assertIn("pg_advisory_xact_lock", implementation) self.assertIn("ConstantTimeCompare", implementation) def test_concurrency_batch_and_limits_are_not_hardcoded_to_16(self) -> None: migration = normalized(text("deploy/postgres/008_control_api.sql")) server = text("Sense/internal/controlapi/server.go") store = text("Sense/internal/store/control_postgres.go") self.assertIn("resource_version bigint not null default 1", migration) self.assertIn("len(body.Items) > 128", server) self.assertIn("limit > 100", server) self.assertIn("SAVEPOINT ", store) self.assertNotIn("len(body.Items) > 16", server) def test_audit_v1_is_unchanged_and_v2_is_a_strict_superset(self) -> None: first = json.loads(text("docs/contracts/sense-device-audit-v1.schema.json")) second = json.loads(text("docs/contracts/sense-device-audit-v2.schema.json")) v1_events = set(first["properties"]["event_type"]["enum"]) v2_events = set(second["properties"]["event_type"]["enum"]) self.assertEqual( {"device.created", "device.desired_state.accepted"}, v1_events ) self.assertEqual(v1_events | {"device.configuration.accepted"}, v2_events) self.assertIn("configurationData", second["$defs"]) def test_disabled_reconciliation_deletes_only_exact_path(self) -> None: reconciler = text("Sense/internal/reconcile/reconciler.go") media = text("Sense/internal/mtx/client.go") self.assertIn("candidate.Device.DesiredState == device.DesiredDisabled", reconciler) self.assertIn("r.media.DeletePath(ctx, candidate.Device.PathName)", reconciler) self.assertIn("Deletion is an idempotent convergence operation", media) self.assertNotIn("ListPaths", reconciler) if __name__ == "__main__": unittest.main()