Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
5af5eb4
test(ea-projection): define fail-closed contract admission boundary
seonghobae Sep 1, 2026
37bbaa1
test(ea-projection): cover kind and temporal interval branches
seonghobae Sep 1, 2026
ae09329
feat(ea-projection): enforce released-contract admission boundary
seonghobae Sep 1, 2026
ad4a638
test(ea-projection): reject type and empty-reference bypasses
seonghobae Sep 1, 2026
c3e4a51
fix(ea-projection): reject unvalidated boundary objects
seonghobae Sep 1, 2026
4910251
test: require context contract admission provenance
seonghobae Sep 1, 2026
e5594c0
fix: fail closed without context contract admission
seonghobae Sep 1, 2026
d7afb7b
docs: distinguish release identity from contract admission
seonghobae Sep 1, 2026
0841367
test: reject mutated EA projection candidates
seonghobae Sep 1, 2026
96f8ab8
test: require immutable candidate collections at readiness
seonghobae Sep 1, 2026
9963c6a
fix: revalidate EA projection candidates at admission
seonghobae Sep 1, 2026
0b5b0e0
docs: record EA candidate runtime-integrity gate
seonghobae Sep 1, 2026
7ff7007
test(ea-projection): reject comparison-overriding trust text
seonghobae Sep 1, 2026
636f9e8
fix(ea-projection): require exact trust-bearing text
seonghobae Sep 1, 2026
3f46384
test(ea-projection): reject behavior-bearing time providers
seonghobae Sep 1, 2026
26141a3
test(ea-projection): reject behavior-bearing datetime subclasses
seonghobae Sep 1, 2026
08b9ba0
fix(ea-projection): freeze temporal runtime types at trust boundary
seonghobae Sep 1, 2026
233d7e1
docs(ea-projection): document immutable temporal runtime boundary
seonghobae Sep 1, 2026
2f2b128
fix(ea-projection): preserve temporal validation contract messages
seonghobae Sep 1, 2026
8a3cc07
test(ea-projection): bind readiness to Orgmetra source revision
seonghobae Sep 1, 2026
23142a7
fix(ea-projection): preserve source identity in readiness evidence
seonghobae Sep 1, 2026
699acb8
docs(ea-projection): bind readiness to source revision
seonghobae Sep 1, 2026
29a0985
test(ea-projection): prevent readiness mutation after admission
seonghobae Sep 1, 2026
3521de5
fix(ea-projection): make readiness decision immutable
seonghobae Sep 1, 2026
0c5b017
docs(ea-projection): record immutable readiness boundary
seonghobae Sep 1, 2026
52130fa
test(ea): bind readiness to exact candidate evidence
seonghobae Sep 1, 2026
a1cb03d
fix(ea): bind readiness to exact candidate evidence
seonghobae Sep 1, 2026
c5d9a86
docs(ea): document candidate-bound readiness evidence
seonghobae Sep 1, 2026
71de679
test(ea): pin runner admission regression
seonghobae Sep 1, 2026
901c3c1
fix(ci): use explicit available Ubuntu runner
seonghobae Sep 1, 2026
adf8a91
chore(ea): defer runner selector to canonical CI repair
seonghobae Sep 1, 2026
dc6ed99
chore(ea): remove duplicate runner contract
seonghobae Sep 1, 2026
6e55443
test(ci): reject floating runner in EA projection workflow
seonghobae Sep 1, 2026
07b58ca
fix(ci): pin EA projection runner image
seonghobae Sep 1, 2026
1dcf131
test(ea): document runner contract module
seonghobae Sep 1, 2026
635eeef
test(ea): require immutable release admission evidence
seonghobae Sep 1, 2026
c52b9b9
fix(ea): make contract trust evidence immutable
seonghobae Sep 1, 2026
99da43d
test(ea): require compatibility and migration receipts
seonghobae Sep 1, 2026
4a1e1c1
test(ea): block admission without lifecycle receipts
seonghobae Sep 1, 2026
b9d5532
fix(ea): require compatibility and migration evidence
seonghobae Sep 1, 2026
d0b2f8f
test(ea): cover each missing lifecycle receipt
seonghobae Sep 1, 2026
c225eba
test(ea): reject one receipt reused for two results
seonghobae Sep 1, 2026
aae9ca0
fix(ea): keep lifecycle receipts distinct
seonghobae Sep 1, 2026
f929fa4
test(ea): reject pre-release admission evidence
seonghobae Sep 1, 2026
7e55ec3
fix(ea): order release and admission verification
seonghobae Sep 1, 2026
8d97d0d
docs(ea): explain lifecycle verification order
seonghobae Sep 1, 2026
6de6e98
test(ea): reject reused admission evidence identities
seonghobae Sep 2, 2026
c746bf0
fix(ea): separate admission evidence identities
seonghobae Sep 2, 2026
07db2ba
docs(ea): document independent evidence identities
seonghobae Sep 2, 2026
7b448a1
test: require declared EA projection concept scope
seonghobae Sep 2, 2026
7546208
fix: align EA projection kinds with declared scope
seonghobae Sep 2, 2026
920cd4a
docs: align EA projection scope with executable kinds
seonghobae Sep 2, 2026
6daf46f
test: fail closed without trusted control-plane evidence
seonghobae Sep 2, 2026
a0552d9
test: keep caller evidence blocked after lifecycle validation
seonghobae Sep 2, 2026
0671774
test: separate receipt validity from trust authorization
seonghobae Sep 2, 2026
1791dff
test: retain source binding while trust gate is closed
seonghobae Sep 2, 2026
8530450
fix: require repository-owned trust before EA handoff
seonghobae Sep 2, 2026
dc57685
docs: make trusted-control-plane gate explicit
seonghobae Sep 2, 2026
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
56 changes: 56 additions & 0 deletions .github/workflows/enterprise-architecture-projection-quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Enterprise Architecture Projection Quality

on:
pull_request:
branches:
- bootstrap
- develop
- main
paths:
- "packages/enterprise-architecture-projection/**"
- ".github/requirements/foundation-test.txt"
- ".github/workflows/enterprise-architecture-projection-quality.yml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: enterprise-architecture-projection-quality-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
unit:
name: EA projection admission and 100% coverage
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout exact candidate
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Prove exact candidate checkout
env:
ORGMETRA_EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: test "$(git rev-parse HEAD)" = "$ORGMETRA_EXPECTED_HEAD_SHA"
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
check-latest: false
- name: Install reviewed test toolchain
run: |
python -m pip install --require-hashes --no-deps --only-binary=:all: -r .github/requirements/foundation-test.txt
python -m pip check
- name: Compile Enterprise Architecture projection boundary
run: python -m compileall -q packages/enterprise-architecture-projection/src packages/enterprise-architecture-projection/tests
- name: Test projection admission with exact statement and branch coverage
env:
PYTHONPATH: packages/enterprise-architecture-projection/src
COVERAGE_FILE: /tmp/orgmetra-enterprise-architecture-projection.coverage
run: python -m pytest -c packages/enterprise-architecture-projection/pyproject.toml packages/enterprise-architecture-projection/tests
- name: Require clean checkout
run: |
git diff --exit-code
test -z "$(git status --porcelain)"
29 changes: 29 additions & 0 deletions packages/enterprise-architecture-projection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Enterprise Architecture projection admission

This package is the Orgmetra-side fail-closed boundary for Enterprise Architecture projection candidates. It exists to keep two systems of record separate: Orgmetra owns HRIS/HCM facts, while the Enterprise Architecture Decision Plane owns accepted architecture truth.

It does **not** publish directly to Enterprise Architecture Core, reproduce `context-graph-contracts`, or carry person, employment, job, position, assignment, performance, selection, or other authoritative HR record payloads. Cross-service database access is not part of this boundary.

## Current operating state

`ContractReleaseEvidence` and `ContractAdmissionEvidence` are validation shapes, not trust capabilities. They are directly constructible Python values, so a caller can never obtain an authorized handoff merely by filling them with plausible release tags, digests, receipt identities, or verification times. `evaluate_projection_readiness` validates their shape and internal relationships but remains fail-closed even when every current field is complete.

The first gate is an immutable published `ContextualWisdomLab/context-graph-contracts` release. Without one, the next action is `install_approved_context_graph_contract_release`. Release identity alone is deliberately insufficient: the exact released commit and artifact must also be bound to executable semantic conformance, the complete published contract bundle, and artifact provenance. Missing semantic admission keeps the next action at `verify_released_context_graph_contract_admission`.

Semantic admission still does not prove that a released contract is safe for this consumer. Exact compatibility and migration receipts must be bound to the admitted release. Missing lifecycle receipts produce the separate fail-closed next action `verify_context_graph_contract_compatibility_and_migration`. Conformance, complete-bundle, provenance, compatibility, and migration evidence are independent controls: each retained receipt must have its own SHA-256 identity, malformed or reused receipt identity is rejected, and an explicit no-migration-required result still needs a real digest-bound migration receipt. Admission verification must be at or after the release-verification instant, so pre-release lifecycle evidence cannot satisfy the validation boundary.

Even shape-complete release and admission evidence remains blocked with `trusted_control_plane_evidence_not_available` and the next action `integrate_released_context_graph_trust_contract`. Orgmetra does not yet have a repository-owned production adapter that can establish that those external values came from an owner-authorized trust source. Documentation alone is not used as an authorization mechanism.

The package does not guess or reproduce an unreleased Context Assertion, CloudEvent, API schema, profile, issuer, signing-key contract, signature format, admission receipt, provenance format, compatibility result, or migration result. Once the Context Graph owner publishes its immutable trust and verification contract, Orgmetra must implement a repository-owned ACL/control-plane adapter against that released contract and add consumer tests proving that caller-created or unsigned external evidence cannot produce a positive handoff. Only that trusted adapter may unlock a future `proposed` candidate for submission to the Enterprise Architecture owner. Acceptance, replacement, lifecycle decisions, and authoritative EA truth remain separate EA-owner decisions.

## Candidate scope

Permitted projection concepts are deployable architecture concerns: applications, services, APIs, workers, databases, runtimes, interfaces, technology components and versions, providers, lifecycle, risk, ownership, remediation, supported capabilities, initiatives, transformations, and dependencies. Projection evidence preserves Orgmetra source revision, effective time, recorded time, non-person ownership references, architecture-only dependency references, and the exact external evidence identities validated by this boundary.

Every decision carries the exact validated Orgmetra source repository and source revision **and** a SHA-256 over the exact allowed candidate evidence snapshot used by the decision. That digest covers the projection identity and kind, source identity, effective and recorded times, architecture owner, and dependency references. A decision for one candidate therefore cannot be treated as evidence for a different candidate merely because both came from the same Orgmetra commit.

Candidate construction is not the only integrity boundary. `evaluate_projection_readiness` revalidates the retained candidate, detaches the values used for the decision into an immutable local snapshot, validates that snapshot again, and then computes the candidate evidence digest. A caller cannot use low-level frozen-dataclass mutation to replace a validated architecture owner with a Person reference, restore a mutable dependency collection, or detach the decision evidence from the values that were actually evaluated. The resulting readiness decision is tuple-backed immutable evidence rather than a frozen dataclass, so low-level `object.__setattr__` cannot rewrite a blocked decision into a ready handoff after evaluation.

Trust-bearing timestamps use exact built-in `datetime` values paired with Python's immutable built-in fixed-offset `timezone`. Behavior-bearing `datetime` subclasses and caller-defined mutable `tzinfo` providers are rejected both when candidate evidence is retained and when release/admission evidence is evaluated. This prevents a value that initially appears timezone-aware from changing offset or comparison behavior after validation and silently rewriting effective, recorded, or verification-time meaning.

The package intentionally exposes no free-form payload field. If a future use case needs additional fields, add them explicitly with RED tests proving that HR record data cannot cross the boundary.
24 changes: 24 additions & 0 deletions packages/enterprise-architecture-projection/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[build-system]
requires = ["setuptools>=69"]
build-backend = "setuptools.build_meta"

[project]
name = "orgmetra-enterprise-architecture-projection"
version = "0.1.0"
description = "Fail-closed admission boundary for Orgmetra enterprise-architecture projections."
requires-python = ">=3.12"

[project.optional-dependencies]
test = ["pytest>=8.3", "pytest-cov>=5.0"]

[tool.setuptools.packages.find]
where = ["src"]

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = [
"--cov=orgmetra_enterprise_architecture_projection",
"--cov-branch",
"--cov-report=term-missing",
"--cov-fail-under=100",
]
Loading
Loading