Add enterprise appliance experience Phase 1 foundation

This commit is contained in:
Jino Jose committed 2026-07-12 12:13:23 +05:30
1 parent b3eec34158
commit ebaa2e7219
69 files changed
+6832 -18

No files matched your search

+1
View File
@@ -0,0 +1 @@
"""Nexus One AI test package."""
+24
View File
@@ -0,0 +1,24 @@
# Phase 1 WCAG 2.2 AA Checklist
Apply to browser setup, console-equivalent instructions, landing readiness, appliance and health
pages. Automated checks supplement but do not replace manual review.
- [ ] Keyboard completes valid setup, validation recovery and interruption recovery.
- [ ] Focus order follows the visible journey and remains visible at all times.
- [ ] Validation errors are associated with fields and focus moves to the first invalid field.
- [ ] Progress, degraded state, failure and completion are announced without stealing focus.
- [ ] Step, tier and tool selectors expose name, role, state and keyboard operation.
- [ ] Confirmation identifies scope, disruption and recovery implications.
- [ ] Status and severity never rely on colour alone.
- [ ] Text and controls meet WCAG 2.2 AA contrast requirements.
- [ ] Content reflows at 320 CSS pixels and remains usable at 200% zoom.
- [ ] Motion respects reduced-motion preferences.
- [ ] Page titles, headings, landmarks and labels identify purpose and context.
- [ ] Error messages avoid raw codes as primary text and provide a safe next action.
- [ ] Workstation and Server labels are consistent and understandable.
- [ ] Restricted-network guidance is locally available.
- [ ] Automated scan has no unresolved Level A or AA finding.
- [ ] Representative screen-reader journey has no unresolved blocker.
Record browser, operating system, assistive technology, viewport, product configuration, evidence
links, reviewer and date for every completed run.
+1
View File
@@ -0,0 +1 @@
"""Backend contract tests."""
+21
View File
@@ -0,0 +1,21 @@
import ast
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
MAIN = ROOT / "ansible/roles/cezen-backend/files/main.py"
def load_symbols(*names, globals_dict=None):
tree = ast.parse(MAIN.read_text())
wanted = []
for node in tree.body:
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name in names:
wanted.append(node)
elif isinstance(node, ast.Assign):
assigned = {target.id for target in node.targets if isinstance(target, ast.Name)}
if assigned.intersection(names):
wanted.append(node)
namespace = dict(globals_dict or {})
exec(compile(ast.Module(body=wanted, type_ignores=[]), str(MAIN), "exec"), namespace)
return namespace
+18
View File
@@ -0,0 +1,18 @@
from ._source import load_symbols
def _namespace():
return load_symbols("_AUDIT_SENSITIVE_KEYS", "_redact_audit_value", "safe_audit_detail", globals_dict={"json": __import__("json")})
def test_structured_audit_detail_redacts_secret_categories():
safe = _namespace()["safe_audit_detail"]({"license_key": "abc", "result": "valid", "nested": {"token": "xyz"}})
assert "abc" not in safe and "xyz" not in safe
assert safe.count("[REDACTED]") == 2
assert "valid" in safe
def test_text_audit_detail_redacts_key_value_pairs():
safe = _namespace()["safe_audit_detail"]("license_key=abc token:xyz outcome=valid")
assert "abc" not in safe and "xyz" not in safe
assert "outcome=valid" in safe
@@ -0,0 +1,24 @@
from datetime import datetime, timezone
from ._source import load_symbols
def test_customer_state_normalizes_unknown_values():
ns = load_symbols("CUSTOMER_STATES", "customer_state", globals_dict={"utcnow": lambda: datetime.now(timezone.utc).isoformat()})
payload = ns["customer_state"]("mystery", "Status cannot be observed")
assert payload["schema"] == "cezen.customer_state.v1"
assert payload["state"] == "unavailable"
assert payload["summary"] == "Status cannot be observed"
def test_error_envelope_has_customer_safe_fields():
ns = load_symbols("error_envelope")
payload = ns["error_envelope"]("service_unavailable", "Model service is unavailable", "Retry after checking health.", affected_scope="local inference", correlation_id="corr-1")
assert set(payload) == {"schema", "code", "message", "remediation", "affected_scope", "correlation_id"}
assert payload["correlation_id"] == "corr-1"
def test_new_operation_interfaces_require_admin_in_source():
source = (__import__("pathlib").Path(__file__).resolve().parents[2] / "ansible/roles/cezen-backend/files/main.py").read_text()
assert 'actor.get("role") != "admin"' in source
assert '"admin_required"' in source
+17
View File
@@ -0,0 +1,17 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
def test_canonical_and_deployed_license_helpers_are_identical():
canonical = ROOT / "scripts/cezen_license.py"
deployed = ROOT / "ansible/roles/cezen-backend/files/cezen_license.py"
assert canonical.read_bytes() == deployed.read_bytes()
def test_customer_labels_preserve_compatibility_slugs():
source = (ROOT / "scripts/cezen_license.py").read_text()
for slug in ("starter", "basic", "pro", "max"):
assert slug in source
assert 'WORKSTATION_TIER = "workstation"' in source
+31
View File
@@ -0,0 +1,31 @@
import sqlite3
from ._source import load_symbols
def _migration_namespace():
return load_symbols("SCHEMA_VERSION", "_column_names", "run_migrations")
def test_migration_is_idempotent_and_creates_operation_contract():
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE audit_log (id INTEGER PRIMARY KEY, detail TEXT)")
ns = _migration_namespace()
assert ns["run_migrations"](db) == 1
assert ns["run_migrations"](db) == 1
columns = {row[1] for row in db.execute("PRAGMA table_info(operations)")}
assert {"id", "correlation_id", "kind", "state", "idempotency_key", "recovery_actions"} <= columns
assert "correlation_id" in {row[1] for row in db.execute("PRAGMA table_info(audit_log)")}
def test_newer_schema_is_rejected_without_mutation():
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE schema_metadata (key TEXT PRIMARY KEY, value TEXT NOT NULL)")
db.execute("INSERT INTO schema_metadata VALUES ('schema_version','999')")
ns = _migration_namespace()
try:
ns["run_migrations"](db)
except RuntimeError as exc:
assert "newer than supported" in str(exc)
else:
raise AssertionError("newer schema was accepted")
+25
View File
@@ -0,0 +1,25 @@
import sqlite3
from ._source import load_symbols
def test_operation_states_include_recovery_and_terminal_states():
ns = load_symbols("OPERATION_STATES", "TERMINAL_OPERATION_STATES")
assert {"requested", "running", "awaiting_reboot", "recovery_required"} <= ns["OPERATION_STATES"]
assert ns["TERMINAL_OPERATION_STATES"] <= ns["OPERATION_STATES"]
def test_operation_schema_prevents_duplicate_kind_and_idempotency_key():
ns = load_symbols("SCHEMA_VERSION", "_column_names", "run_migrations")
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE audit_log (id INTEGER PRIMARY KEY, detail TEXT)")
ns["run_migrations"](db)
values = ("1", "c1", "install", "requested", "now", "now", "same")
sql = "INSERT INTO operations (id,correlation_id,kind,state,requested_at,updated_at,idempotency_key) VALUES (?,?,?,?,?,?,?)"
db.execute(sql, values)
try:
db.execute(sql, ("2", "c2", "install", "requested", "now", "now", "same"))
except sqlite3.IntegrityError:
pass
else:
raise AssertionError("duplicate idempotent operation accepted")
+23
View File
@@ -0,0 +1,23 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
MAIN = ROOT / "ansible/roles/cezen-backend/files/main.py"
def test_readiness_contract_has_state_freshness_impact_and_actions():
source = MAIN.read_text()
assert '"cezen.readiness_report.v2"' in source
for field in ("observed_at", "freshness_seconds", "affected_capabilities", "next_actions"):
assert field in source
def test_readiness_contract_preserves_entitlement_reasons():
source = MAIN.read_text()
for reason in ("not_licensed", "not_provisioned", "unsupported_hardware", "degraded", "unavailable"):
assert reason in source
def test_readiness_display_target_is_ten_seconds():
spec = " ".join((ROOT / "specs/001-enterprise-experience/spec.md").read_text().split())
assert "within 10 seconds" in spec
+16
View File
@@ -0,0 +1,16 @@
# Browser Journey and Accessibility Tests
Browser tests MUST run against a disposable local or appliance target, never a production customer.
Required coverage:
- supported desktop browser viewport plus 200% zoom/reflow;
- keyboard-only primary and failure/recovery journeys;
- visible focus, logical order, accessible names, headings and landmarks;
- dynamic status, progress, validation and completion announcements;
- loading, empty, ready, degraded, failed, restricted, unavailable and stale states;
- 1-second navigation feedback and 2-second operation acknowledgement trials;
- screenshots and machine-readable results stored outside source control.
The final browser runner and dependency versions MUST be pinned when implementation selects them.
Automated accessibility results never replace the manual WCAG 2.2 AA checklist.
+26
View File
@@ -0,0 +1,26 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
WEB_SETUP = ROOT / "autoinstall/websetup/server.py"
def test_web_setup_exposes_validation_and_customer_facing_license_labels():
source = WEB_SETUP.read_text()
assert "validate_static_network" in source
assert "LICENSE_STATUS_LABELS" in source
assert "Invalid signature — re-upload a valid signed license" in source
def test_phase1_contract_requires_durable_progress_not_only_process_memory():
source = WEB_SETUP.read_text()
# This test intentionally fails until T026 replaces process-local-only state.
assert "INSTALL_OPERATION_JSON" in source
assert "idempotency_key" in source
assert "operation_id" in source
def test_setup_acknowledgement_contract_is_explicit():
source = WEB_SETUP.read_text()
assert "acknowledged_at" in source
assert "duplicate_request" in source
+34
View File
@@ -0,0 +1,34 @@
from __future__ import annotations
import importlib.util
import os
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parents[1]
BACKEND_MAIN = REPO_ROOT / "ansible/roles/cezen-backend/files/main.py"
@pytest.fixture
def isolated_appliance(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> dict[str, Path]:
"""Return isolated appliance paths and never touch /opt/cezen."""
data = tmp_path / "data"
backups = tmp_path / "backups"
data.mkdir()
backups.mkdir()
monkeypatch.setenv("CEZEN_DATA", str(data))
monkeypatch.setenv("CEZEN_BACKUP_DIR", str(backups))
monkeypatch.setenv("CEZEN_LICENSE_JSON", str(tmp_path / "license.json"))
return {"root": tmp_path, "data": data, "backups": backups}
def load_backend_module(module_name: str = "cezen_backend_test"):
"""Load the packaged backend only after fixtures set environment variables."""
spec = importlib.util.spec_from_file_location(module_name, BACKEND_MAIN)
if spec is None or spec.loader is None:
raise RuntimeError(f"Cannot load backend from {BACKEND_MAIN}")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
+18
View File
@@ -0,0 +1,18 @@
# Deployment Validation
Run from the repository root on a safe validation host.
```bash
bash -n install.sh autoinstall/firstboot-setup.sh autoinstall/build-iso.sh \
autoinstall/build-iso-workstation.sh autoinstall/build-iso-starter.sh
ansible-playbook --syntax-check ansible/starter.yml
ansible-playbook --syntax-check ansible/entry.yml
ansible-playbook --syntax-check ansible/pro.yml
ansible-playbook --syntax-check ansible/max.yml
python3 -m py_compile ansible/roles/cezen-backend/files/main.py \
ansible/roles/cezen-backend/files/cezen_license.py autoinstall/websetup/server.py
```
Syntax checks do not prove installation. Phase 1 additionally requires clean-install, interruption,
reboot/resume, restricted-network, migration, backup/restore and source-to-artifact evidence on one
representative Workstation and one representative Server.
+21
View File
@@ -0,0 +1,21 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
FIRSTBOOT = ROOT / "autoinstall/firstboot-setup.sh"
def test_console_setup_preserves_workstation_separation_and_safe_completion():
source = FIRSTBOOT.read_text()
assert 'WORKSTATION_MODE' in source
assert 'TIER_DISPLAY="workstation"' in source
assert 'touch /opt/cezen/.setup-done' in source
assert source.index('touch /opt/cezen/.setup-done') > source.index('if bash "$AIPACKAGE_DIR/install.sh"')
def test_console_setup_has_resume_and_recovery_contract():
source = FIRSTBOOT.read_text()
# Intentionally red until T028 adds durable console progress.
assert "cezen.setup_operation.v1" in source
assert "recovery_required" in source
assert "resume" in source.lower()
+18
View File
@@ -0,0 +1,18 @@
# Appliance Test Fixtures
## Supported Baseline
Capture the exact prior released revision, package/ISO checksum, Ubuntu version, product category,
commercial tier, schema version and enabled components before migration testing. A moving `main`
checkout is not a valid baseline.
## Restore Fixture Requirements
- Synthetic users, audit events, settings and operational state only.
- No real credentials, signed licenses, customer documents or private logs.
- Valid checksums and a documented schema/product version.
- Representative Workstation and Server install records.
- Valid, missing/staging, expired, invalid-signature and mismatch license fixtures using test keys.
- Corrupt, incomplete and incompatible backup fixtures for negative testing.
Fixtures containing secrets or customer content MUST NOT enter source control.
+29
View File
@@ -0,0 +1,29 @@
{
"schema": "cezen.test.setup_matrix.v1",
"configurations": [
{
"id": "representative-workstation",
"category": "workstation",
"commercial_label": "Nexus One AI Workstation",
"compatibility_profile": "starter",
"expected_server_tier_menu": false,
"journeys": ["valid", "field-staging", "invalid-license", "network-loss", "service-failure", "reboot-resume", "stale-readiness"]
},
{
"id": "representative-server-m",
"category": "server",
"commercial_label": "Server M",
"compatibility_tier": "basic",
"expected_server_tier_menu": true,
"journeys": ["valid", "field-staging", "invalid-license", "hardware-restriction", "network-loss", "service-failure", "reboot-resume", "stale-readiness"]
}
],
"common_assertions": [
"non-secret progress persists",
"duplicate submission is idempotent",
"customer-facing state is truthful",
"safe next action is present",
"restricted-network help is local",
"WCAG 2.2 AA evidence is recorded"
]
}