16 KiB
Verification Report
Change: notify-approved-access-requests
Version: N/A
Mode: Strict TDD
Verified branch/commit: backup/local-work-before-remote-update / working tree after final strict-TDD scenario coverage
Verification date: 2026-05-13
Completeness
| Metric | Value |
|---|---|
| Tasks total | 79 |
| Tasks complete | 77 |
| Tasks incomplete | 2 |
Incomplete tasks in openspec/changes/notify-approved-access-requests/tasks.md:
- Phase 0:
0.3production env confirmation forINVITATION_BASE_URL=https://app.omnioil.appandSMTP_*remains unchecked. - Phase 9:
9.6manual happy path with stubbed SMTP remains unchecked because this focused verification used automated DB integration evidence, not browser/manual SMTP QA.
Phase 5 backend DB integration tasks are now complete: the ignored harness ran against the disposable PostgreSQL/Timescale fixture and passed 5/5, covering provisioning, SMTP-failure persistence, invalid activation rejection, resend token rotation, and non-provider/customer admin denial through production handlers/routes.
Build & Tests Execution
Build: ➖ Not run — user constraint says do not build.
Tests / targeted verification commands:
-
Current focused verification:
$env:DATABASE_URL='postgres://omnioil_test:omnioil_test_password@127.0.0.1:55432/omnioil_access_request_test'; cargo test -p backend-api --test access_request_db_integration -- --ignored --nocapture- ✅ 5 passed, 0 failed, 0 ignored.
- Passed tests:
approve_pending_and_in_review_requests_provision_customer_accesssmtp_failure_persists_provisioning_and_failed_email_statusinvalid_activation_tokens_do_not_change_user_or_invitation_stateresend_revokes_previous_unconsumed_tokens_and_creates_fresh_invitationcustomer_admin_is_forbidden_from_provider_console_resend_route_without_rotating_tokens
- Non-failing warnings: 4 dead-code warnings for helper functions/types used only by unit tests.
-
Current focused unit evidence:
$env:SQLX_OFFLINE='true'; cargo test -p backend-api access_request_emails- ✅ 2 passed, 0 failed.
-
Current focused unit evidence:
$env:SQLX_OFFLINE='true'; cargo test -p backend-api auth- ✅ 5 passed, 0 failed.
-
Retained prior backend targeted evidence:
$env:SQLX_OFFLINE='true'; cargo test -p backend-api access_requests- ✅ 10 passed, 0 failed, 16 filtered.
-
Retained prior backend targeted evidence:
$env:SQLX_OFFLINE='true'; cargo test -p backend-api invitations- ✅ 3 passed, 0 failed, 23 filtered.
-
Retained prior backend targeted evidence:
$env:SQLX_OFFLINE='true'; cargo test -p backend-api invitation_tokens- ✅ 3 passed, 0 failed, 19 filtered.
-
Retained prior backend targeted evidence:
$env:SQLX_OFFLINE='true'; cargo test -p backend-api smtp_mailer- ✅ 2 passed, 0 failed, 20 filtered.
-
Retained prior frontend evidence:
pnpm --dir services/frontend-admin test -- ActivatePage- ✅ Focused activation-page tests passed.
-
Retained prior frontend evidence:
pnpm --dir services/frontend-console test -- AccessRequestsPage- ✅ 17 passed, 0 failed.
-
Not rerun in this focused pass:
cargo fmt -- --check
- ⚠️ External waiver candidate. Prior focused verification showed it fails only on unrelated repo-wide Rust formatting drift outside this SDD change. Per maintainer direction, do not mix the global formatting cleanup into this feature and do not mark it as an in-scope feature failure.
Coverage: ➖ Not available (openspec/config.yaml marks coverage unavailable).
TDD Compliance
| Check | Result | Details |
|---|---|---|
| TDD Evidence reported | ✅ | Engram sdd/notify-approved-access-requests/apply-progress contains a TDD Cycle Evidence table. |
| All tasks have tests | ✅ | The final three previously untested scenarios now have runtime coverage: customer admin provider denial, activation-link construction, and non-provider resend rejection. |
| RED confirmed (tests exist) | ✅ | Apply-progress records RED for the DB harness/library extraction before src/lib.rs existed. |
| GREEN confirmed (tests pass) | ✅ | Real DB harness passed 5/5 against disposable PostgreSQL on port 55432; focused unit suites for link/auth passed. |
| Triangulation adequate | ✅ | DB harness covers multiple persisted-state branches: pending/in-review, re-approval rejection, active existing user, provider duplicate, SMTP failure, invalid tokens, and resend rotation. |
| Safety Net for modified files | ✅ | Targeted backend unit suites and DB integration harness evidence exist; frontend focused suites are retained from prior verify/apply passes. |
TDD Compliance: 6/6 checks pass for the automated strict-TDD scenario coverage requested in this pass.
Test Layer Distribution
| Layer | Tests | Files | Tools |
|---|---|---|---|
| Unit / structural | 22 backend tests in accumulated focused evidence | Rust module tests | cargo test |
| DB integration | 5 passed scenario tests | services/backend-api/tests/access_request_db_integration.rs |
cargo test -p backend-api --test access_request_db_integration -- --ignored --nocapture with explicit DATABASE_URL |
| Integration / component | 17 Console tests + focused Admin activation tests retained from prior evidence | TSX test files | Vitest + Testing Library / React DOM |
| E2E | 0 | 0 | Available project scripts, not used |
Changed File Coverage
Coverage analysis skipped — no coverage tool detected.
Assertion Quality
Assertion quality: ✅ No tautology or ghost-loop assertions found in inspected related tests. The DB integration tests assert persisted database state through production handlers instead of smoke checks.
Quality Metrics
Linter: ➖ Not rerun in this focused pass; prior verify/apply evidence reported frontend lint passing.
Formatter: ⚠️ External waiver candidate — not rerun in this focused pass; prior evidence showed repo-wide cargo fmt -- --check fails only on unrelated Rust formatting drift outside this SDD change.
Type Checker: ➖ Not run — no build/type-check command executed under the user constraint.
Spec Compliance Matrix
| Requirement | Scenario | Test | Result |
|---|---|---|---|
| Approve Request Provisions Customer Access | Approving a pending request provisions new customer admin | access_request_db_integration > approve_pending_and_in_review_requests_provision_customer_access |
✅ COMPLIANT |
| Approve Request Provisions Customer Access | Approving an in-review request provisions access | access_request_db_integration > approve_pending_and_in_review_requests_provision_customer_access |
✅ COMPLIANT |
| Approve Request Provisions Customer Access | Approving a closed request is rejected | access_request_db_integration > approve_pending_and_in_review_requests_provision_customer_access re-approval assertion |
✅ COMPLIANT |
| Existing User Is Linked, Not Duplicated | Existing user email is approved again | access_request_db_integration > approve_pending_and_in_review_requests_provision_customer_access active-customer branch |
✅ COMPLIANT |
| Existing User Is Linked, Not Duplicated | Existing active user is linked | access_request_db_integration > approve_pending_and_in_review_requests_provision_customer_access; access_requests > active_user_resend_sends_access_ready_notification_without_invitation_rotation |
✅ COMPLIANT |
| Customer Roles Remain Separated From Provider Roles | Provisioned customer admin cannot access provider Console | auth > customer_admin_role_does_not_satisfy_platform_claims; access_request_db_integration > customer_admin_is_forbidden_from_provider_console_resend_route_without_rotating_tokens |
✅ COMPLIANT |
| Activation Invitation Uses Secure Opaque Token | Activation token is created securely | invitation_tokens; access_requests > provisioning_audit_metadata_never_contains_raw_activation_token; DB harness asserts invitation rows exist but not raw token persistence directly |
⚠️ PARTIAL |
| Activation Invitation Uses Secure Opaque Token | Activation link targets customer Admin app | access_request_emails > activation_link_uses_configured_invitation_base_url_and_activate_path; activation_email_defaults_to_production_admin_activate_url |
✅ COMPLIANT |
| Activation Sets Password And Enables Login | Valid activation succeeds | ActivatePage success test; backend activation success path structurally exists, but DB harness focuses invalid-token no-op |
⚠️ PARTIAL |
| Activation Sets Password And Enables Login | Expired activation is rejected | access_request_db_integration > invalid_activation_tokens_do_not_change_user_or_invitation_state; invitations > expired_consumed_and_revoked_invitations_cannot_activate |
✅ COMPLIANT |
| Activation Sets Password And Enables Login | Consumed activation is rejected | access_request_db_integration > invalid_activation_tokens_do_not_change_user_or_invitation_state; invitations > expired_consumed_and_revoked_invitations_cannot_activate |
✅ COMPLIANT |
| Activation Sets Password And Enables Login | Revoked activation is rejected | access_request_db_integration > invalid_activation_tokens_do_not_change_user_or_invitation_state; invitations > expired_consumed_and_revoked_invitations_cannot_activate |
✅ COMPLIANT |
| Approval Email Delivery Is Recoverable | Email send succeeds | access_requests > invitation_email_delivery_update_marks_success_as_sent_and_clears_error; no SMTP-accepted DB integration test found |
⚠️ PARTIAL |
| Approval Email Delivery Is Recoverable | Email send fails | access_request_db_integration > smtp_failure_persists_provisioning_and_failed_email_status; Console failed resend UI test |
✅ COMPLIANT |
| Resend Rotates Activation Tokens | Resend invalidates previous token | access_request_db_integration > resend_revokes_previous_unconsumed_tokens_and_creates_fresh_invitation; Console resend API/UI test |
✅ COMPLIANT |
| Resend Rotates Activation Tokens | Resend is provider-only | auth > customer_admin_role_does_not_satisfy_platform_claims; access_request_db_integration > customer_admin_is_forbidden_from_provider_console_resend_route_without_rotating_tokens |
✅ COMPLIANT |
| Initial Trial Is Created Without Full Billing Automation | Approved project starts trial | access_request_db_integration > approve_pending_and_in_review_requests_provision_customer_access; smtp_failure_persists_provisioning_and_failed_email_status |
✅ COMPLIANT |
| Initial Trial Is Created Without Full Billing Automation | Trial expiration does not belong to activation token | Backend activation query ignores subscription/trial state; no runtime test found | ⚠️ PARTIAL |
| Console Shows Provisioning State | Approved request detail shows provisioning status | AccessRequestsPage.test.tsx > shows provisioned project...; backend ACCESS_REQUEST_SELECT unit test |
✅ COMPLIANT |
| Console Shows Provisioning State | Failed email shows resend action | AccessRequestsPage.test.tsx > shows resend action for failed invitation... |
✅ COMPLIANT |
| Console Shows Provisioning State | Sent email without expiration issue hides urgent resend | AccessRequestsPage.test.tsx > shows provisioned project... and expired/consumed test |
✅ COMPLIANT |
Compliance summary: 16/21 scenarios compliant, 5/21 partial, 0/21 untested.
Correctness (Static — Structural Evidence)
| Requirement | Status | Notes |
|---|---|---|
| Approve Request Provisions Customer Access | ✅ Implemented + DB tested | Approval transaction creates project/user/access/trial/invitation and status; DB harness passed. |
| Existing User Is Linked, Not Duplicated | ✅ Implemented + DB tested | Existing active user is linked without password reset/deactivation; provider-role duplicate is blocked. |
| Customer Roles Remain Separated From Provider Roles | ✅ Implemented + tested | New users use role admin; PlatformClaims rejects customer roles; DB route test proves customer admin receives 403 from provider resend without token rotation. |
| Activation Invitation Uses Secure Opaque Token | ✅ Mostly | Token helper uses 32 random bytes and SHA-256 hash; activation-link construction is unit-tested for INVITATION_BASE_URL, /activate, production default, and raw token query parameter; direct DB raw-token absence remains covered by prior audit/unit evidence. |
| Activation Sets Password And Enables Login | ⚠️ Partial | Public activation endpoint validates hash/state, hashes password, activates user, consumes invitation, and audits activation; invalid-token DB safety is tested, valid backend activation DB success is not directly tested. |
| Approval Email Delivery Is Recoverable | ✅ Failure path DB tested / ⚠️ success path partial | SMTP failure persists approval/provisioning and marks email failed. SMTP accepted path is helper-tested, not DB/SMTP-integrated. |
| Resend Rotates Activation Tokens | ✅ Implemented + DB tested | Provider resend route revokes unconsumed invitations and creates a fresh token for inactive users; active users receive access-ready notification. |
| Initial Trial Is Created Without Full Billing Automation | ✅ Implemented + DB tested | DB harness asserts trial subscription rows for provisioned projects. |
| Console Shows Provisioning State | ✅ Implemented + UI tested | Backend returns display fields; Console displays state and resend actions. |
| Docs And Deployment | ✅ Structural | Deployment docs and env examples document invitation base URL, SMTP variables, 7-day trial, and SMTP failure resend guidance without secrets. |
Coherence (Design)
| Decision | Followed? | Notes |
|---|---|---|
ADR-1 auto-create edge_projects |
✅ Yes | DB harness proves project row creation; unit tests prove deterministic defaults. |
ADR-2 customer role admin |
✅ Yes | New users use admin; provider roles are blocked for duplicate email. |
| ADR-3 existing email links user | ✅ Yes | DB harness proves existing active customer user is linked and preserved. |
| ADR-4 inactive until activation | ✅ Yes | DB harness proves newly provisioned users are inactive. |
| ADR-5 hash-only opaque token | ✅ Mostly | Token/hash helpers and audit metadata tests exist; direct DB raw-token absence assertion remains partial. |
ADR-6 Admin /activate |
✅ Yes | Backend route and Admin page exist; production URL is documented. |
| ADR-7 SMTP failure does not rollback | ✅ Yes | DB harness proves approval/provisioning survive SMTP-disabled failure and invitation status becomes failed. |
| ADR-8 resend revokes prior tokens | ✅ Yes | DB harness proves previous open invitations are revoked, consumed invitations are preserved, and a fresh open invitation is created. |
| ADR-9 7-day trial | ✅ Yes | DB harness proves subscriptions(status='trial', trial_ends_at IS NOT NULL) exists. |
Issues Found
CRITICAL — must fix before strict SDD archive
None for the final three strict-TDD scenario gaps requested in this pass.
WARNING
- Phase
0.3production env confirmation remains unchecked. This is an operational release/deploy readiness item, not a feature-code failure. - Phase
9.6manual happy path remains unchecked. Automated DB evidence now covers the backend path, but no browser/manual stubbed-SMTP happy path was performed in this focused verification. - SMTP accepted delivery is helper-tested but not DB/SMTP-integrated; the failure/recovery path is now DB-tested.
EXTERNAL / WAIVER CANDIDATE
- Repo-wide Rust formatting drift remains external to this feature. Do not mark it as an in-scope failure and do not fix it inside this change unless explicitly authorized as a separate cleanup.
Resolved Since Prior Verify
- Phase 5 DB integration blocker resolved — real disposable PostgreSQL evidence passed 4/4 using the production-handler harness.
- Phase 9.1 complete — targeted backend DB integration command passed.
- Final three strict-TDD scenario gaps resolved — customer
adminprovider denial, activation-link target construction, and non-provider resend rejection now have runtime tests.
Verdict
PASS WITH WARNINGS for automated strict-TDD scenario coverage; remaining warnings are release-readiness/manual verification items.
There is no remaining Phase 5 DB integration blocker and the three previously untested strict scenarios now have runtime coverage. Repo-wide cargo fmt drift remains external. Production env confirmation and manual SMTP happy path remain release-readiness tasks.