diff --git a/_bmad-output/architecture/architecture-ping-mee-self-service-platform-2026-10-15/ARCHITECTURE-SPINE.md b/_bmad-output/architecture/architecture-ping-mee-self-service-platform-2026-10-15/ARCHITECTURE-SPINE.md index cd2c931..f0915c4 100644 --- a/_bmad-output/architecture/architecture-ping-mee-self-service-platform-2026-10-15/ARCHITECTURE-SPINE.md +++ b/_bmad-output/architecture/architecture-ping-mee-self-service-platform-2026-10-15/ARCHITECTURE-SPINE.md @@ -45,7 +45,7 @@ Arrows are the only allowed dependency direction. Views never call adapters. Fea ### AD-2 — Directory access is allow-listed and injection-proof - **Binds:** FR-1, FR-5, FR-8, FR-9, FR-10, FR-14, FR-20; NFR §8.1 - **Prevents:** LDAP injection, writes outside the OU, writes of unlisted attributes, the service account used anywhere else -- **Rule:** the Service Account is used only inside `directory`. Filters are built only with LDAP filter escaping; DNs are never built from input — the DN is found by searching `sAMAccountName` inside the configured OU. Writable attributes are a fixed allow-list: `givenName`, `sn`, `displayName`, `mail`, `telephoneNumber`, `mobile`, `unicodePwd`. Readable attributes are also a fixed allow-list: the writable ones, `sAMAccountName`, `memberOf` (or a group-membership query), `thumbnailPhoto`, `pwdLastSet`, the account's enabled and locked state, and the Password Policy (the domain's `minPwdLength`, `pwdProperties`, `pwdHistoryLength`, `minPwdAge`, `maxPwdAge`, and the user's `msDS-ResultantPSO` when a fine-grained policy applies). The Service Account's read rights are limited to the same list. Everything runs over LDAPS with certificate verification against a CA bundle supplied by environment variable (the homelab uses an internal CA); verification is never disabled. +- **Rule:** the Service Account is used only inside `directory`. Filters are built only with LDAP filter escaping; DNs are never built from input — the DN is found by searching `sAMAccountName` inside the configured OU. Writable attributes are a fixed allow-list: `givenName`, `sn`, `displayName`, `mail`, `telephoneNumber`, `mobile`, `unicodePwd`. Readable attributes are also a fixed allow-list: the writable ones, `sAMAccountName`, `memberOf` (or a group-membership query), `thumbnailPhoto`, `pwdLastSet`, the account's enabled and locked state, and the Password Policy (the domain's `minPwdLength`, `pwdProperties`, `pwdHistoryLength`, `minPwdAge`, `maxPwdAge`, and the user's `msDS-ResultantPSO` when a fine-grained policy applies). The portal reads only the attributes on this list. The Service Account is given no rights beyond the writes above and the Change Password right; its read access is the Active Directory default for authenticated accounts and is not narrowed further. Everything runs over LDAPS with certificate verification against a CA bundle supplied by environment variable (the homelab uses an internal CA); verification is never disabled. ### AD-3 — Self-service acts on the session user only - **Binds:** FR-5, FR-8, FR-10..FR-15, FR-21 diff --git a/_bmad-output/initiative-ping-mee-portal/deferred-work.md b/_bmad-output/initiative-ping-mee-portal/deferred-work.md index 36602af..2eb2ae1 100644 --- a/_bmad-output/initiative-ping-mee-portal/deferred-work.md +++ b/_bmad-output/initiative-ping-mee-portal/deferred-work.md @@ -1,6 +1,3 @@ -- source_plan: `_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-prepare-the-test-environment-plan.md` - summary: ARCHITECTURE-SPINE AD-2 says the service account's read rights are limited to a list, but Active Directory gives authenticated users broad read by default, so the statement is not enforced by the test-environment setup. - evidence: The setup script grants only write rights and the Change Password right; read access is the default. Either soften AD-2 ("needs no more than this list") or enforce it with deny entries; decide when the architecture is next updated. - source_plan: `_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-audit-throttle-and-session-foundations-plan.md` summary: Concurrent writers on the throttle counters are not tested. evidence: The test database is SQLite in memory with a shared cache, which answers "table is locked" to a second writer at once, so a threaded test fails for reasons that say nothing about production (a WAL file database with a 20 s busy timeout and IMMEDIATE transactions). A real test needs a file database; tried and dropped in the refactor sweep. diff --git a/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-refactor-sweep-plan.md b/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-refactor-sweep-plan.md index 610038d..08d505e 100644 --- a/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-refactor-sweep-plan.md +++ b/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-refactor-sweep-plan.md @@ -28,7 +28,7 @@ review_source: 'pinned' | 4 | Lint rules that would have caught 2 and 3 are not on | sweep | patch | `SIM` and `RUF100` added to the ruff rules. | | 5 | `sign_in` test helper lived in `test_signin.py` and was imported by another test module | sweep | patch | Moved to `portal/tests/helpers.py`. | | 6 | AD-6 names `end_sessions(username, except_current=bool)`; the code has `end_sessions(user, except_session_key=None)` | deferred from entry 3 | patch (document) | AD-6 reworded to match the code. | -| 7 | AD-2 says the service account's read rights are limited to a list; Active Directory gives authenticated users broad read | deferred from entry 2 | defer | Needs the owner's decision: soften the sentence or enforce with deny entries. Stays in `deferred-work.md`. | +| 7 | AD-2 says the service account's read rights are limited to a list; Active Directory gives authenticated users broad read | deferred from entry 2 | patch (document) | Owner decided to soften: AD-2 now says the portal reads only the listed attributes and the account gets no rights beyond the writes and Change Password; broad default read is normal for AD. | | 8 | Concurrent writers on the throttle counters are not tested | deferred from entry 3 | defer | A threaded test fails on the in-memory test database for reasons unrelated to production; tried and dropped. Recorded in `deferred-work.md`. | | 9 | Dead code | sweep (vulture) | none | Everything flagged is a framework hook, a setting, or an interface used by later epics. | | 10 | Docker build and browser look of entries 6 and 7 | "not verified" in the plans | closed | Checked on the Linux host by the owner (build, shell, test e-mail). |