Skip to content

test: Wave 2 — model/DB integration P1 spine (102 tests) + a PasswordHistory fix#61

Merged
WebTigers merged 2 commits into
mainfrom
test/int-wave2
Jul 24, 2026
Merged

test: Wave 2 — model/DB integration P1 spine (102 tests) + a PasswordHistory fix#61
WebTigers merged 2 commits into
mainfrom
test/int-wave2

Conversation

@WebTigers

Copy link
Copy Markdown
Owner

Wave 2 of the test backfill — the integration/DB model spine (COVERAGE-PLAN §6.1, the P1 tenant-isolation + auth data layer). Four parallel agents, each written against its own isolated database (no cross-contention), then collected and verified together against one DB: 111 integration tests / 374 assertions green.

Clusters (+102 tests)

  • Data-layer base (28) — Tiger_Model_Table tested hardest: v7/v4 UUID mint, actor+org tenant stamp (immutable created_by), and the soft-delete activeSelect/findById exclusion invariant every model rides on; Config/Option scope isolation; Db_Migrator ordering/idempotency/apply-after-success/rollback.
  • Auth models (21) — AuthChallenge single-use/expiry/attempt-lock/hashed-at-rest; UserCredential password verify + pepper-migration rehash + PAT/recovery single-use + lockout + TOTP encrypt-at-rest; User verified-factor identity; PasswordHistory; Policy_Password reuse across the pepper boundary.
  • Content/CMS (27) — Page org cascade + publish/schedule gate + phtml-stored-not-executed; Media public-direct-vs-private-streamer URL scoping + classify() allowlist; Menu tenant cascade + reorder ownership guard; Org siteOrgId/slug/hierarchy; Page/CodeVersion.
  • ACL/module/session (26) — Acl{Resource,Role,Rule} soft-delete exclusion (a dropped rule can't keep granting); Module inactiveSlugs boot gate (active-by-absence); Login windowed failure math; Session gc per-row expiry + deleteByUserId; Translation.

A real bug the tests surfaced — fixed here

Tiger_Model_PasswordHistory::recentForUser() silently ignored its $limit — a Zend_Db_Table_Select passed to fetchAll() makes ZF1 drop the $count arg, so it returned all retained rows regardless (stricter-than-configured, not a hole). Fix: the limit now lives on the Select; the regression test pins that it takes.

Findings tracked (no change — see COVERAGE-PLAN §9)

  • ACL loaders filter deleted=0 only, not status — a status='inactive' rule still loads/affects decisions.
  • AuthChallenge::redeem() single-use is a non-atomic TOCTOU — fine single-threaded; wants a conditional UPDATE … WHERE consumed_at IS NULL under concurrent load.

Runs green in CI (unit 8.1–8.5 + integration on MariaDB). Next: Wave 3 (the /api service + auth-service spine — needs login()/installAcl() helpers added to the integration base first).

🤖 Generated with Claude Code

WebTigers and others added 2 commits July 24, 2026 13:03
…asswordHistory limit fix

Four parallel integration clusters (each against an isolated DB during dev, verified together
against one DB at collection: 111 tests / 374 assertions green):

- Data-layer base (28): Tiger_Model_Table tested hardest — v7/v4 UUID mint, actor+org tenant
  stamp (immutable created_by), soft-delete + activeSelect/findById exclusion (the tenant-safety
  invariant); Config/Option scope isolation; Db_Migrator ordering/idempotency/apply-after-success/rollback.
- Auth models (21): AuthChallenge single-use/expiry/attempt-lock/hashed-at-rest; UserCredential
  password verify + pepper-migration rehash + PAT/recovery single-use + lockout + TOTP encrypt-at-rest;
  User verified-factor identity; PasswordHistory ordering/prune; Policy_Password reuse across the pepper boundary.
- Content/CMS (27): Page org cascade + publish/schedule gate + phtml-stored-not-executed; Media
  public-direct-vs-private-streamer URL scoping + classify allowlist; Menu tenant cascade + reorder
  ownership guard; Org siteOrgId/slug/hierarchy; Page/CodeVersion nextVersion.
- ACL/module/session (26): Acl{Resource,Role,Rule} soft-delete exclusion (a dropped rule can't
  keep granting); Module inactiveSlugs boot gate (active-by-absence); Login windowed failure math;
  Session gc per-row expiry + deleteByUserId; Translation override tier.

FIX (a test surfaced it): Tiger_Model_PasswordHistory::recentForUser() ignored its $limit — a Select
passed to fetchAll() makes ZF1 drop the $count arg, so it returned ALL retained rows (stricter-than-
configured, not a hole). Moved the limit ONTO the Select; the regression test now pins that it takes.

Findings tracked (no change): ACL loaders filter deleted=0 only, not status (a status='inactive' rule
still loads); AuthChallenge::redeem() single-use is a non-atomic TOCTOU (fine single-threaded, wants a
conditional UPDATE under load). See COVERAGE-PLAN §9.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@WebTigers
WebTigers merged commit 1bda627 into main Jul 24, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant