chore: add GRACE semantic contracts across agent + backend + build scripts
- Add @RELATION/@RATIONALE/@REJECTED headers to agent modules - Add GRACE contracts to backend services, models, schemas - Update build.sh with single-image build commands (build:backend|frontend|agent) - Update docker entrypoint: openssl rsa → openssl pkey (alg-agnostic) - Add @RATIONALE to backend core modules (cot_logger, config_manager, ssl)
This commit is contained in:
@@ -12,6 +12,13 @@
|
||||
# @POST User identity verified and session tokens issued according to role scopes.
|
||||
# @SIDE_EFFECT Writes last login timestamps and JIT-provisions external users.
|
||||
# @DATA_CONTRACT [Credentials | ADFSClaims] -> [UserEntity | SessionToken]
|
||||
# @RATIONALE Thin service layer between API routes and AuthRepository — encapsulates credential
|
||||
# verification (password hashing), ADFS JIT provisioning, and session creation into
|
||||
# a single orchestration class. This keeps route handlers free of auth business logic.
|
||||
# @REJECTED Putting credential verification logic directly in API route handlers was rejected —
|
||||
# it would be duplicated across local login, ADFS callback, and API-key auth paths.
|
||||
# Authentication was kept separate from authorization (permission checks in middleware)
|
||||
# to allow independent testing of each concern.
|
||||
|
||||
from datetime import UTC, datetime
|
||||
from typing import Any
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
# @INVARIANT Artifact catalog must produce deterministic CandidateArtifact entries with required identity and checksum fields.
|
||||
# @SIDE_EFFECT Reads JSON file from filesystem
|
||||
# @DATA_CONTRACT FilePath -> CandidateArtifact[]
|
||||
# @RATIONALE ArtifactCatalogLoader provides a standalone entry point for loading release
|
||||
# candidate manifests from JSON files — used by the TUI and API to bootstrap
|
||||
# clean-release flows without requiring an already-configured release pipeline.
|
||||
# The JSON artifact catalog is human-editable for manual overrides.
|
||||
# @REJECTED Embedding artifact loading in the compliance orchestrator was rejected — the
|
||||
# loader must work independently for TUI-based workflows where no orchestrator
|
||||
# exists. A DB-backed artifact store was rejected for the bootstrap flow —
|
||||
# the release process starts before the database may be fully configured.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
# @PRE PolicyRepository is accessible
|
||||
# @POST PolicyDecision returned with approval status
|
||||
# @SIDE_EFFECT Read-only policy evaluation; no state changes
|
||||
# @RATIONALE Policy evaluation is a pure function from Candidate -> PolicyDecision, enabling
|
||||
# deterministic unit tests without database mocking. The "enterprise-clean" policy
|
||||
# rejects dashboards referencing non-registry datasources — this prevents deploying
|
||||
# dashboards that depend on ad-hoc tables or views that won't exist in production.
|
||||
# @REJECTED Executing policy checks inside the deployment pipeline was rejected — policy failures
|
||||
# should be surfaced during release preparation, not after deployment begins. An
|
||||
# allow-list approach (listing permitted sources) was rejected as too brittle — the
|
||||
# registry-based approach (any source not in the registry is a violation) automatically
|
||||
# catches new unregistered sources without policy updates.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
@@ -10,6 +10,14 @@
|
||||
# @PRE PolicyRepository and Manifest are available
|
||||
# @POST ResolutionResult with matched policies
|
||||
# @SIDE_EFFECT Read-only policy evaluation; logs resolution decisions
|
||||
# @RATIONALE PolicyResolutionService decouples snapshot resolution from policy evaluation — it
|
||||
# resolves the active policy and registry snapshots from ConfigManager's environment
|
||||
# configuration, then passes them to PolicyEngine for evaluation. This separation
|
||||
# allows testing resolution logic without evaluating policies, and vice versa.
|
||||
# @REJECTED Merging resolution and evaluation into one service was rejected — resolution depends
|
||||
# on ConfigManager (which environment is target), while evaluation is a pure function
|
||||
# over snapshots. Combining them would require mocking ConfigManager even for unit
|
||||
# testing simple policy rules.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
# @INVARIANT Stage execution is deterministic for equal input context.
|
||||
# @SIDE_EFFECT None (deterministic execution)
|
||||
# @DATA_CONTRACT Context -> StageResult
|
||||
# @RATIONALE Pluggable stage architecture isolates each compliance check (manifest integrity,
|
||||
# internal-only sources, data purity, etc.) into a self-contained Protocol-based stage.
|
||||
# Each stage receives a shared ComplianceContext and produces a StageResult — the
|
||||
# orchestrator aggregates results without knowing stage internals. This allows adding
|
||||
# new compliance checks without modifying the execution pipeline.
|
||||
# @REJECTED Monolithic compliance check was rejected — a single function checking all rules would
|
||||
# exceed INV_7 (400 lines) and require coordinated changes for every new policy. Using
|
||||
# inheritance (base class with abstract methods) was rejected — Protocol-based structural
|
||||
# subtyping is more testable with simple dataclass contracts instead of class hierarchies.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
# @PRE session is active and valid
|
||||
# @POST Returns Report with generated summary
|
||||
# @SIDE_EFFECT Read-only database operations; logs report generation
|
||||
# @RATIONALE Module-level contract aggregates task report normalization and query services
|
||||
# into a single namespace consumed by route handlers. Normalization logic is extracted
|
||||
# as a pure function (normalize_task_report) to enable unit testing without DB state.
|
||||
# @REJECTED Splitting normalization and query into separate modules was rejected — they always
|
||||
# change together (when a new task type is added, both the normalizer and query filter
|
||||
# must be updated), making separation artificial overhead.
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
@@ -81,6 +87,14 @@ def _filter_tasks_by_rbac(tasks: list[Task], current_user) -> list[Task]:
|
||||
# @SIDE_EFFECT Reads task history and optional clean-release repository state without mutating source records.
|
||||
# @DATA_CONTRACT Input[TaskManager, Optional[CleanReleaseRepository], ReportQuery|report_id] -> Output[ReportCollection|ReportDetailView|None]
|
||||
# @INVARIANT Service methods are read-only over task history source.
|
||||
# @RATIONALE ReportService provides a read-only query layer over TaskManager + CleanReleaseRepository
|
||||
# — separate from the task execution pipeline — so that report UIs don't need access to
|
||||
# task creation or lifecycle APIs. Service methods normalize task records into a consistent
|
||||
# ReportRow shape regardless of the originating plugin (migration, translate, etc.).
|
||||
# @REJECTED Embedding report queries in TaskManager was rejected — it would mix read-only analytics
|
||||
# with task execution concerns and expose execution internals to report consumers. A
|
||||
# dedicated reporting database was rejected — the operational task store is the SSOT and
|
||||
# syncing to a reporting DB would add latency and consistency risk.
|
||||
#
|
||||
# @TEST_CONTRACT ReportsServiceModel ->
|
||||
# {
|
||||
|
||||
Reference in New Issue
Block a user