Files
Ebbe BaßandClaude Sonnet 5.5 24de5878ed Add BMAD planning artifacts: brief, PRD, architecture, UX, spec, tickets
Includes the BMAD install config, the initiative ticket tree, the portal
context-resources scripts, and the .gitignore change that tracks BMAD files
(generated _bmad/render/ is ignored).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sk72AxLwQnYttF6VFSxQLt
2026-10-15 13:33:02 +02:00

7.8 KiB

scope, purpose, altitude, updated
scope purpose altitude updated
ping-mee self-service portal, whole system (greenfield) build substrate for epics/stories; architecture spine initiative 2026-10-15T11:22
  • (constraint) Input: PRD _bmad-output/prds/prd-ping-mee-self-service-platform-2026-10-15 (prd.md FR-1..FR-29, addendum.md) is binding; its non-goals and decisions are inherited silently.
  • (constraint) Deployment: ONE Docker container on Linux behind existing reverse proxy (TLS terminated there); all config + secrets via env vars; nothing ping-mee-specific baked in; internet-exposed.
  • (constraint) Integrations: OIDC (authentik, generic OIDC); LDAPS to AD with a least-privilege service account (OU + attrs givenName,sn,displayName,mail,telephoneNumber,mobile,password); SMTP (IONOS, configurable); SMB share (write source/.jpg, read processed/.md5); existing PowerShell sync scripts unchanged.
  • (constraint) Scale: ~10 users; hard security bar (no injection, no session takeover, no cross-user access, throttling in front of every AD bind).
  • (constraint) Open from PRD for architecture: Q-1 share unreachable, Q-2 mail retry/IONOS limits, Q-3 languages, Q-4 absolute session max, Q-5 data store/backup, Q-6 removed-AD-user cleanup, Q-7 removed-picture pending, Q-8 time zone, Q-9 md5 timing.
  • (decision) Mode: COACHING. Audience: only Ebbe + AI agents (spine only; no extra human-facing artifact requested yet). User has NO stack preference - delegates choice to architect.
  • (version) Django: 5.2 LTS (security support to Apr 2028), 6.0.x current as of Oct 2026 per web search (source: endoflife.date / djangoproject.com); next LTS 6.2 Apr 2027. Verify exact pin when scaffolding.
  • (version) ldap3 (pure Python): last PyPI release 2.9.1 ~4 years ago, single maintainer -> stagnant. python-ldap: healthy, releases within last 3 months, needs libldap/libsasl build deps. Both can set AD unicodePwd over ldaps.
  • (version) pillow-heif: 1.3.0 (Feb 2026) on PyPI per search, newer 1.6.0 in Arch testing Aug 2026; HEIC/AVIF decode 8/10/12-bit. Verify pin.
  • (version) Fluent UI Blazor (Microsoft.FluentUI.AspNetCore.Components) 4.13.x documents .NET 8/9; .NET 10 support not confirmed -> weakens the .NET option.
  • (decision) STACK [user-chosen, option A]: Python + Django (5.2 LTS or current; pin at scaffold), server-rendered pages, python-ldap (not ldap3: stagnant), Pillow + pillow-heif. Rejected: ASP.NET/Blazor (HEIC, .NET10 Fluent unconfirmed, Blazor circuits vs session kill), Node/React (SPA attack surface, HEIC), Go (cgo HEIC, hand-built). Binds: all units use Django ORM/sessions/CSRF/templates; Prevents: parallel hand-rolled web/auth layers.
  • (direction) Office 365 look via Microsoft Fluent web components as static assets in server-rendered templates (UNVERIFIED - check at UX/scaffold).
  • (decision) PARADIGM [ADOPTED by user]: modular monolith, Django project, one app per feature (accounts, profile, picture, announcements, adminui, audit) + external-world adapters with ONE OWNER each: directory (only LDAP/service account), mailer (only SMTP), share (only picture folders), idp (OIDC). No other module imports ldap/smtplib or touches share paths. Prevents: scattered AD/file access, injection surface.
  • (decision) INVARIANT [agreed]: self-service actions always operate on the session user; no username taken from URL/form. Every state change writes its Audit Entry in the SAME transaction in the service layer (not view). Roles from AD group membership cached briefly (default 60s, setting).
  • (decision) DATA STORE (Q-5) [user-confirmed constraints]: SQLite on a mounted volume, ONE gunicorn worker with threads + one in-process scheduler thread; scale-out not supported without moving to PostgreSQL. Backups: Veeam copy-job copies directories -> portal must write consistent SQLite backups (online backup API) into a backups/ dir on the volume on a schedule; Veeam must not rely on copying the live DB file.
  • (decision) Q-4: absolute session max 4h (plus 1h idle). Q-3: German AND English, all text translatable from day one. Q-8: store UTC, display Europe/Berlin default (configurable), zone named in e-mails. Share: host mounts CIFS, container gets bind mounts source (rw) + processed (ro).
  • (decision) CLIENT IP: reverse proxy is Zoraxy (per issue tobychui/zoraxy#93): appends real client IP to X-Forwarded-For and forwards an existing X-Real-IP UNCHANGED (spoofable). Rule: if TCP peer is in TRUSTED_PROXIES, client IP = rightmost X-Forwarded-For entry (trusted-proxy count configurable); NEVER use X-Real-IP; else use peer address. Verify with a test request at deploy.
  • (decision) ENVIRONMENTS: no staging and no test AD. Only prod AD/authentik. Test OU can be created: a non-prod instance of the SAME image points at a test OU with a test service account scoped to it (OU, groups, share paths all config). Adapters have fakes; automated tests need no real AD/IdP/SMTP; manual smoke checklist against the test OU.
  • (decision) DEPLOY: docker compose by hand on Linux host; image location not stated (assume built on host or private registry - deferred). Veeam copy-job notifies on copy failure only; portal MUST show last-successful-backup age + failed jobs (backup, mail outbox) in Admin UI because a portal-side backup failure would be invisible to Veeam. No alert e-mail; Admin UI status is enough (user).
  • (decision) SECURITY [proposed, no objection]: Authlib for OIDC (code flow + PKCE, verify state/nonce/signature); throttle counters in DB keyed endpoint+user and endpoint+IP, checked BEFORE any directory call; sensitive actions re-verify password via directory adapter after throttle; passwords memory-only, never logged; secure HttpOnly cookies, CSRF everywhere, strict CSP (no inline script), security headers; DB sessions with username column; one-query session kill.
  • (decision) OPS [proposed, no objection]: multi-stage image, non-root, only data/backups/share writable; entrypoint migrates then starts, fail-fast on missing env; /healthz checks DB only (not AD); JSON logs to stdout with request id, no secrets; 30s idempotent state-driven scheduler tick (no scheduler lib) running publish, outbox send, token expiry, audit retention, DB backup, nightly AD reconciliation; upgrade = backup, migrate; rollback = restore + previous tag.
  • (decision) MAIL [proposed]: outbox table, per-recipient rows, retries/backoff + rate limit for IONOS, no direct sending. Q-6: nightly reconciliation deletes opt-outs/pending changes/picture state of users gone from OU; audit kept to retention. Q-1: share adapter atomic write (tmp+rename) with timeouts, error to user, no state change. Q-7/Q-9: Pending clears when processed md5 == stored md5; for removal when processed md5 != previous md5; sync-writes-md5-before-AD limitation accepted + timeout message.
  • (version) nh3 (Rust ammonia binding) is the maintained HTML sanitizer; bleach deprecated Jan 2023. nh3 0.2.x on PyPI. Markdown parser: markdown-it-py (not verified; pin at scaffold).
  • (version) @fluentui/web-components v3.0.0 stable 29 Jun 2026, v3.0.1 7 Jul 2026; framework-agnostic. DECISION: vendor built assets into the image at build time (no runtime CDN) - strict CSP and supply-chain; Node only in build stage.
  • (version) Authlib 1.7.x current (June 2026 release) - verified by search; mozilla-django-oidc 4.0.1 (2024) older.
  • (event) Gate: lint clean; adversarial pass done inline (no subagents). Fixes: LDAPS CA bundle via env (internal CA); SessionUser(key,sam) canonical identity; AD-call-inside-transaction semantics; mailer owns outbox; email plain-text + sanitized HTML; AD-19 one owner per table; single logout deferred. Independent subagent reviewers NOT run.
  • (event) spine finalized
  • (change) Update pass from UX run: AD-2 read allow-list incl. Password Policy + pwdLastSet; AD-13 accent colour + contrast warning; AD-15 per-device preferences cookies + de formal/informal; AD-16 rich-text editor -> Markdown, assets bundled; capability map FR-30..32; stack row for editor library (chosen at scaffold).