Skip to content
2 changes: 1 addition & 1 deletion .agent-loop/CURRENT_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ authority; these records do not grant or withhold it.

| Initiative | Durable state on `main` | Remaining boundary |
|---|---|---|
| [WS-ARCH-001](initiatives/WS-ARCH-001-modular-monolith-boundaries/STATUS.md) | Boundary foundation and TASK, PROJECT, CHECKER, ART hidden preparation, and ART admission-consumption module-level capabilities are complete through `WS-ARCH-001-02E`; no product route or AUTH action was activated | `WS-ARCH-001-02F` is the TASK-owned immutable Submission command and hidden composed transaction |
| [WS-ARCH-001](initiatives/WS-ARCH-001-modular-monolith-boundaries/STATUS.md) | Boundary foundation and hidden submission capabilities are complete through `WS-ARCH-001-02F`, including the TASK-owned atomic Submission composition; no product route or AUTH action was activated | `WS-ARCH-001-02G` is the AUTH contributor-preparation activation boundary |
| [WS-ART-001](initiatives/WS-ART-001-immutable-artifact-storage/STATUS.md) | Active delivery initiative; verified ready-admission publication and hidden preparation are merged through `04C2` | Replace the non-executable 05-wave XINT/ART contracts with WS-ARCH-001 split public-API contracts before activation, Submission consumption, or live cutover |
| [WS-AUTH-001](initiatives/WS-AUTH-001-workstream-authorization-service/STATUS.md) | Active delivery initiative; project-policy authority and unified compilation authorization are merged through `12I` | POL-03B consumes 12I next; remaining AUTH activation chunks wait for their exact hidden owner behavior |
| [WS-CON-001](initiatives/WS-CON-001-contribution-compensation-boundary/STATUS.md) | Active delivery initiative; policy persistence and shared lifecycle audit are merged | Complete hidden services, contribution records, conditional awards, fulfillment, and reconciliation after named AUTH and REV gates |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
| `WS-ARCH-001-02C` | CHECKERS effective pre-submit plan and bounded execution-result public facts/ports | L1 | Merged PR #320; no contributor preparation action or public route activated |
| `WS-ARCH-001-02D` | ART hidden preparation public API and private-edge migration | L1 | Complete; production remains deny-only |
| `WS-ARCH-001-02E` | ART ready-admission consumption and binding hidden module-level capability | L1 | Complete; production remains deny-only and route-unreachable |
| `WS-ARCH-001-02F` | TASK-owned immutable Submission command and hidden composed transaction | L1 | Next durable boundary |
| `WS-ARCH-001-02G` | AUTH contributor preparation activation after the complete hidden path | L1 | Proposed after 02F |
| `WS-ARCH-001-02F` | TASK-owned immutable Submission command and hidden composed transaction | L1 | Complete; production remains deny-only and route-unreachable |
| `WS-ARCH-001-02G` | AUTH contributor preparation activation after the complete hidden path | L1 | Next durable boundary |
| `WS-ARCH-001-02H` | AUTH human/fixed-service consumption activation | L1 | Proposed after 02G |
| `WS-ARCH-001-02I` | Admission-only public API/dispatch cutover and complete legacy removal | L1 | Deferred after 02H plus split 03/04/05 remediation, revision, checker-output and REV admission prerequisites |
| `WS-ARCH-001-03` | PROJECT/TASK guide, locked-context, task and assignment capability repairs | L1 | Non-executable placeholder; requires a split contract |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@
route to delivery composition, exposes the bounded ART request/result/command
API, consumes TASK/PROJECT/CHECKER public capabilities, keeps AUTH handles
opaque, and preserves deny-only availability.
- WS-ARCH-001-02E is complete in this change. ART exposes one deny-by-default
- WS-ARCH-001-02E is complete. ART exposes one deny-by-default
ready-admission consumption port, validates exact TASK and ART lineage,
serializes binding identity, persists the consumed Submission id/version,
creates one provider-neutral generic binding, and proves replay, concurrency,
rollback, and stable conflicts without activating a route or AUTH action.
- Next durable boundary: WS-ARCH-001-02F only, the TASK-owned immutable
Submission command and hidden composed transaction. Open pull requests show
transient ownership.
- WS-ARCH-001-02F is complete in this change. TASK owns the immutable
admission-backed Submission command and the adapter owns one hidden root
transaction; production remains deny-only and route-unreachable.
- Next durable boundary: WS-ARCH-001-02G only, AUTH contributor-preparation
activation. Open pull requests show transient ownership.
- Repository housekeeping after PR #315 found no competing clean-up
initiative: WS-ARCH-001 remains the general boundary owner, WS-AUTH-003 owns
AUTH-specific debt, and test-structure repairs remain incremental with the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ WS-ARCH-001 — Modular Monolith Boundaries
## Goal

Implement the TASK-owned immutable Submission command and hidden application
composition that atomically consumes fresh human AUTH, fixed ART-binding AUTH,
ART admission/binding, and TASK persistence through public ports.
composition that atomically consumes deny-only human AUTH, deny-only fixed
ART-binding AUTH, the already-ready ART admission/binding, and TASK persistence
through public ports.

## Why this chunk exists

Expand Down Expand Up @@ -41,18 +42,29 @@ backend/app/modules/tasks/api/**
backend/app/modules/tasks/models.py
backend/app/modules/tasks/repository.py
backend/app/modules/tasks/service.py
backend/app/adapters/**/submission*.py
backend/app/modules/tasks/submission_composition.py
backend/app/adapters/tasks/__init__.py
backend/app/main.py
backend/alembic/versions/<next-current-main-revision>.py
backend/alembic/env.py
backend/tests/test_tasks.py
backend/tests/test_submission_concurrency.py
backend/tests/test_submission_history.py
backend/tests/test_submission_composition.py
backend/tests/test_artifact_bindings_db.py
backend/scripts/run_test_lanes.py
backend/scripts/behavior_ownership.py
backend/tests/test_alembic.py
backend/tests/conftest.py
backend/tests/authorization/guide_compilation/test_migration_contract.py
backend/tests/projects/guide_compilation/test_migration_contract.py
Comment thread
coderabbitai[bot] marked this conversation as resolved.
backend/tests/architecture/test_module_boundaries.py
.ci/module-boundaries/private-edge-debt.v1.json
.ci/behavior-ownership/**
.agent-loop/initiatives/WS-ARCH-001-modular-monolith-boundaries/chunks/WS-ARCH-001-02F-task-submission-composition.md
.agent-loop/initiatives/WS-ARCH-001-modular-monolith-boundaries/CHUNK_MAP.md
.agent-loop/initiatives/WS-ARCH-001-modular-monolith-boundaries/STATUS.md
.agent-loop/CURRENT_STATE.md
.agent-loop/initiatives/WS-ARCH-001-modular-monolith-boundaries/evidence/WS-ARCH-001-02F-transaction-manifest.md
.agent-loop/initiatives/WS-ARCH-001-modular-monolith-boundaries/reviews/WS-ARCH-001-02F-external-review-response.md
docs/architecture_data_model.md
```

Expand All @@ -71,11 +83,15 @@ contribution dispatch; compatibility facade.
transaction as every mutation and evidence row. Production wiring remains
deny-only; this chunk proves denial/concealment and zero mutation, not a
successful AUTH capability or complete business effect.
- [ ] `PreparedBundlePreSubmitEvidenceService.persist(...)` joins that root
transaction through its public port and never opens or commits an
independent transaction; an integration test proves a final-stage failure
rolls back the Submission, binding, admission transition, evidence rows,
and authorization evidence together.
- [ ] The command accepts only typed TASK-owned authority ports. It never
receives an AUTH prepared handle, raw authorization context, AUTH
repository/session, or private ART service. The deny-only implementations
conceal the unavailable capability before any protected mutation.
- [ ] Pre-submit evidence and the ready admission are immutable prerequisites
produced by the earlier preparation path; 02F neither re-persists nor
mutates checker evidence. An integration test proves a final-stage failure
rolls back the Submission, binding, admission transition, and any
transaction-local authorization evidence together.
- [ ] Composition opens one unit of work and wires ports only; TASK command owns
sequencing and each owner enforces its invariants.
- [ ] Denial, cancellation and persistence failure roll back all effects;
Expand All @@ -86,11 +102,30 @@ contribution dispatch; compatibility facade.
`.agent-loop/initiatives/WS-ARCH-001-modular-monolith-boundaries/evidence/WS-ARCH-001-02F-transaction-manifest.md`.
- [ ] The new command remains hidden/unreachable pending 02G-02I.

## Required lock and operation order

1. Open one root transaction in the application composition adapter.
2. Consume/conceal the human `submission.create` authority through its typed
deny-only TASK-facing port before protected state is revealed or mutated.
3. Lock TASK, active assignment, and latest predecessor through TASK ownership.
4. Allocate the immutable Submission id and next version from the locked facts.
5. Insert and flush the provisional TASK-owned Submission identity/version so
ART's admission foreign key can be validated inside the same transaction.
6. Call the ART admission-consumption public port with that exact id, version,
and TASK context; ART locks its lineage and consumes fixed binding authority.
7. Attach the exact ART admission/content/binding references to the Submission
and flush the complete immutable row.
8. Consume/record any final TASK-owned authority evidence inside the same root
transaction, then let the composition adapter commit once.

No step may commit independently. Denial or failure at any step rolls back the
whole root transaction.

## Verification commands

```bash
(cd backend && .venv/bin/python -m ruff check app/modules/tasks app/adapters app/main.py tests/test_submission_concurrency.py)
(cd backend && export WORKSTREAM_TEST_DATABASE_URL="${WORKSTREAM_TEST_DATABASE_URL:?set WORKSTREAM_TEST_DATABASE_URL}" && .venv/bin/python -m pytest -q tests/test_tasks.py tests/test_submission_concurrency.py tests/test_submission_history.py tests/test_alembic.py --cov=app.modules.tasks --cov-fail-under=90)
(cd backend && .venv/bin/python -m ruff check app/modules/tasks app/adapters/tasks tests/test_submission_composition.py)
(cd backend && export WORKSTREAM_TEST_DATABASE_URL="${WORKSTREAM_TEST_DATABASE_URL:?set WORKSTREAM_TEST_DATABASE_URL}" && .venv/bin/python -m pytest -q tests/test_submission_composition.py tests/test_tasks.py tests/test_alembic.py --cov=app.modules.tasks --cov-fail-under=90)
(cd backend && .venv/bin/python -m scripts.module_boundaries validate --protected-base origin/main)
python3 scripts/check_stale_authorization_docs.py
python3 scripts/check_stale_artifact_contracts.py
Expand All @@ -112,3 +147,7 @@ lock order, deny-only zero effect, and absence of orchestration-domain drift.

Stop if transaction atomicity requires public sessions/repositories, if ART
must create Submission, or if the live route must change early.

## Merge state

- Outcome on merge: `complete`
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# WS-ARCH-001-02F Transaction Manifest

## Capability

The hidden `SubmissionCreationCommand` creates one TASK-owned immutable
Submission from one already-ready ART admission. It remains route-unreachable
and production authorization remains deny-only.

## Transaction and lock order

1. The TASK adapter opens one root SQLAlchemy transaction.
2. Human `submission.create` authority is checked through the TASK-owned typed
authority port before TASK state is revealed.
3. TASK locks the task, active assignment, and latest predecessor.
4. TASK allocates the Submission UUID and version.
5. TASK inserts and flushes the provisional Submission identity/version.
6. ART consumes the exact admission and fixed binding authority through its
public port, locking ART lineage and binding scope.
7. TASK completes and flushes the immutable Submission with admission, binding,
content, assignment, predecessor, and locked policy references.
8. TASK consumes final human authority using the allocated identity/version.
9. The adapter commits once; every exception or cancellation rolls back all
participants.

## Public facts and ports

- `SubmissionCreationRequest` carries contributor-authored summary and
attestation plus server-selected TASK/assignment/admission/predecessor IDs.
- `SubmissionCreationAuthorizationPort` exposes only preliminary and final
TASK facts; no AUTH handle, context, repository, or session crosses TASK.
- `SubmissionArtifactAdmissionPort` is the TASK-owned participant protocol;
the composition adapter translates it to ART's public
`SubmissionAdmissionConsumptionPort`.
- `SubmissionCreationResult` returns only Submission, admission, binding, and
content identities.

## Protected mutations

- TASK: one immutable `submissions` row.
- ART: one admission terminal transition and one generic artifact binding.
- AUTH: transaction-local decision evidence only after later activation.

Pre-submit checker evidence is an immutable prerequisite and is not mutated by
this command.

## Deny-only state

`DenySubmissionCreationAuthorization` rejects before TASK locks or mutation.
No route, action catalogue entry, or production AUTH adapter is activated by
02F. Positive complete-effect and concurrency proof remains owned by 02H.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# WS-ARCH-001-02F External Review Response

## Comments addressed

- Added every changed planning, state, and PostgreSQL proof file to the chunk's
allowed mutation scope.
- Restricted every new Alembic metadata assertion to the `public` schema.
- Preserved the canonical physical check-constraint name with `op.f(...)`;
hosted schema-contract tests prove it matches the ORM convention.
- Configured the PostgreSQL rollback proof without leaving an implicit
transaction open before the transaction-owning command.

## Comments deferred

None.

## Human decisions needed

None.

## Commands rerun

- Ruff on the changed migration and tests.
- Focused TASK, architecture, and behavior-ownership tests.
- GitHub Backend semantic lanes and Agent Gates on the exact PR head.

## Remaining risks

None identified from the CodeRabbit review threads.
10 changes: 9 additions & 1 deletion .ci/behavior-ownership/partition.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,10 @@
"group": "lifecycle",
"target": "backend/app/modules/reviews/schemas.py"
},
{
"group": "lifecycle",
"target": "backend/app/modules/tasks/api/submission_command.py"
},
{
"group": "lifecycle",
"target": "backend/app/modules/tasks/api/submission_context.py"
Expand Down Expand Up @@ -712,6 +716,10 @@
"group": "lifecycle",
"target": "backend/app/modules/tasks/service.py"
},
{
"group": "lifecycle",
"target": "backend/app/modules/tasks/submission_composition.py"
},
{
"group": "auth",
"target": "backend/app/schemas/auth.py"
Expand Down Expand Up @@ -817,7 +825,7 @@
"target": "backend/scripts/week2_api_e2e.py"
}
],
"authority_digest": "2052bde67b61768756b7a2e342abdb96e311d10bc06709d1f61611f298ea2a7a",
"authority_digest": "6e8c9f70a0917f12e28205d7056404a29e1a0611992b7d87b59c54f96e2b5ea4",
"protected_base_commit": "7676ce4347db0c9694962a9b587a20765e16eac6",
"schema": "workstream.behavior-ownership-partition.v1"
}
2 changes: 1 addition & 1 deletion backend/alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
target_metadata = Base.metadata

_BASELINE_REVISION = "0001_v01_baseline"
_CURRENT_HEAD_REVISION = "0002_admission_version"
_CURRENT_HEAD_REVISION = "0003_submission_lineage"
_RECREATE_GUIDANCE = (
"Workstream v0.1 requires a fresh database; recreate this database before "
"running the 0001_v01_baseline migration"
Expand Down
49 changes: 49 additions & 0 deletions backend/alembic/versions/0003_submission_artifact_lineage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""Add canonical admission and artifact lineage to TASK Submissions."""

from alembic import op
import sqlalchemy as sa

revision = "0003_submission_lineage"
down_revision = "0002_admission_version"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.alter_column("submissions", "package_hash", existing_type=sa.String(128), nullable=True)
op.add_column("submissions", sa.Column("task_assignment_id", sa.String(36)))
op.add_column("submissions", sa.Column("submission_bundle_admission_id", sa.String(36)))
op.add_column("submissions", sa.Column("artifact_binding_id", sa.String(36)))
op.add_column("submissions", sa.Column("artifact_content_id", sa.String(36)))
op.create_foreign_key(
"fk_submissions_task_assignment_id_task_assignments",
"submissions",
"task_assignments",
["task_assignment_id"],
["id"],
)
op.create_index("ix_submissions_task_assignment_id", "submissions", ["task_assignment_id"])
op.create_index(
"ix_submissions_submission_bundle_admission_id",
"submissions",
["submission_bundle_admission_id"],
unique=True,
)
op.create_unique_constraint(
"uq_submissions_artifact_binding_id", "submissions", ["artifact_binding_id"]
)
op.create_check_constraint(
op.f("ck_submissions_artifact_lineage_shape"),
"submissions",
"(task_assignment_id is null and submission_bundle_admission_id is null "
"and artifact_binding_id is null and artifact_content_id is null) or "
"(task_assignment_id is not null and submission_bundle_admission_id is not null "
"and artifact_binding_id is not null and artifact_content_id is not null)",
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
op.create_index("ix_submissions_artifact_content_id", "submissions", ["artifact_content_id"])


def downgrade() -> None:
raise RuntimeError(
"Workstream v0.1 migrations cannot be downgraded; recreate the database"
)
Loading
Loading