DataTalksClub / DataTalksClub/website
Complete Studio production identity, role, audit export, and high-risk controls
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Parent epic: #7
Normative authority
- 06 — Studio and admin API
- 07 — Security, privacy, accessibility, and operations
- 10 — Verification strategy
- Resolved staff-identity decision #20
- Resolved high-risk decision #28
- Resolved privacy decision #23
- Accepted provider-neutral Studio foundation #86
Outcome
Complete the production Studio role, high-risk, audit-export, identity/session-integration, and production Django-admin policy. Studio and the later production admin API remain adapters over the same deny-by-default capability, function/object/field, application-service, concurrency/idempotency, high-risk, and redacted-audit boundaries.
This issue has two distinct delivery states:
- three bounded product slices were independently tested and PM-accepted on an older lineage but have never been committed or integrated; and
- the complete #32 control contract remains unfinished and requires exact owner decisions plus the accepted #61 identity/session handoff.
The bounded reconstruction may land with Refs #32; it must not close the issue or be presented as production identity/high-risk completion.
Current lifecycle state
Audited against current origin/main face8e4808d65afbf0374d1ced7a88079950d663.
- #20, #23, #28, and #86 are satisfied inputs.
- #61 is still open and decision-blocked. The selected shared-Cognito path also lacks accepted external federated-MFA evidence under DataTalksClub/aws-infra#24.
- Current main is not a green delivery base. The active P0 recovery sequence owns the content/source, quality, browser-harness, podcast, homepage, and structured-evidence failures. Do not reconstruct #32 until the orchestrator identifies one green, integrated current-main base.
- The preserved combined candidate is
.tmp/issue-32-accepted-slices-engineer, branchissue-32-accepted-slices-current, base/HEAD9a491cd9baeb1e723bd05e8dacb20978fbaf9d33, with 26 uncommitted paths. It is a reference implementation only. - Its last versioned report is red/incomplete: full Playwright ended with the then-known 21 failures and timeout, independent current-envelope screenshots are pending, and every plan/digest predates
face8e4. No prior test, screenshot, plan, or PM slice acceptance is evidence for a reconstructed source snapshot. - The old patch overlaps current-main changes in
core/views.pyandwebsite/urls.py; later integration also overlapswebsite/settings/base.pywith #265. Do not wholesale rebase, cherry-pick, commit, or merge the old worktree.
Previously accepted bounded behavior
The following product behavior remains the reconstruction target; the prior acceptance does not authorize the old source snapshot itself.
1. Permission-gated Studio audit export
- Redacted CSV snapshot of the currently authorized filtered audit queryset.
- Maximum 1,000 rows and 32 KiB rendered output.
- Strict filters, bounded input, CSRF, current Studio authorization, recent authentication, action-specific explicit confirmation, and idempotent exact replay/conflict behavior.
- Formula neutralization, re-redaction of legacy/directly inserted audit values, private/no-store/noindex responses, and redacted success/denial audit evidence.
- Clear desktop/mobile review, empty, over-limit, stale-authentication, conflict, denial, and download states.
2. Studio role administration
- Exactly the seven code-owned roles from specification 06:
site_admin,content_operator,course_operator,event_operator,email_operator,support_operator, andauditor. - Explicit
core.manage_studio_rolesauthority; active staff targets only; maximum 100 targets with safe over-bound behavior. - Replace only those seven owned groups and preserve every unrelated group.
- Current revision, idempotency, portable concurrency, bounded reason, recent authentication, exact confirmation, generic denial, and redacted audit evidence.
- Private Studio list/review/update/success/error behavior at desktop/mobile widths.
This bounded slice does not claim the final function/object/field matrix for every current and future domain capability, and it does not mount a production admin-API role adapter.
3. Production Django-admin guard
- Django admin is enabled only in explicit local/development/test settings.
- Production fails closed for
/admin,/admin/, login, and nested paths before the public catch-all, returning generic private/no-store/noindex 404 responses. - There is no dedicated break-glass credential or production Django-admin workflow. This consumes #20: emergency recovery uses accepted management-API parity, with direct database access only as the last-resort operational fallback owned by #7.
Bounded reconstruction dispatch gate
After the release-recovery chain produces a clean, green current main, one engineer may reconstruct only the three accepted slices above in a fresh isolated worktree. Reconstruction must preserve current accepted public behavior, including the correct Events and Community knowledgebase headings; stale browser assertions are updated without changing those headings.
Before independent testing, engineering must also close these candidate-specific safety gaps without broadening the product surface:
- Complete export redaction. Nested aliases for raw IP, query string/query parameters, request headers, raw/complete URL, member/user identifiers, actor references, credentials, tokens, bodies, email, and provider payloads must be removed or safely classified before the CSV, replay record, logs, audit, diagnostics, and artifacts. Positive and negative fixtures must prove alias normalization at every supported depth without suppressing the explicitly allowed bounded audit fields.
- Bounded replay and retention. A corrupt/compressed replay value must be decompressed with an enforced output bound rather than allocating an unbounded result. The stored CSV duplicate must have an explicit expiry/cleanup behavior no longer than the underlying one-year minimized-audit retention and must participate in the approved retention/deletion boundary; an expired/removed snapshot cannot be resurrected through replay.
- No evidence leakage. Synthetic identities only. Screenshots, reports, plans, logs, and issue comments contain no email, staff/provider identity, token, cookie, reason text, audit payload, or production data.
The engineer generates a fresh versioned plan from the exact new base/head and runs every selected uv/Make gate. A separate tester recomputes the plan, verifies focused Django and the required full Playwright tier, and captures/opens the role and audit-export journeys at desktop/mobile sizes. PM must reaccept the exact combined current-main snapshot. Only then may a focused commit use Refs #32; #32 remains open.
Integrate this accepted-slices commit before #265 because both touch the settings/bootstrap surface. #265 is an ordering concern, not a product dependency.
Remaining complete-issue scope
Identity/session consumption
- Consume the accepted #61 accounts-owned handoff: one durable local staff user plus current
StaffSessionidentity, authentication time, status, and revocation behavior. - Apply active-account, active-staff, explicit
core.access_studio, offboarding, logout, expiry, and revocation checks without parsing or persisting raw provider claims/tokens/payloads. - Do not implement the OIDC protocol here. #61 owns start/callback/logout, admission/linking, idle/absolute session behavior, outage behavior, and deterministic provider verification.
- Do not claim production staff identity ready until DataTalksClub/aws-infra#24 supplies accepted secret-free evidence for the exact Google Workspace/shared-Cognito MFA path.
Effective role and authorization matrix
- Freeze every management capability present at the implementation baseline with its effective role, Django permission, function policy, authorized queryset/object lookup, sensitive-field policy, Studio adapter, API operation metadata, high-risk class, concurrency/idempotency rule, audit action/redaction, rate class/cost, test factory, and domain owner.
- The seven role names are code-owned defaults, not authorization shortcuts. No generic
is_staff,is_superuser, group-name-only, public editorial Person, compatibility token, or future/wildcard capability grants authority. - Unknown capabilities, policies, fields, targets, and later-added domain actions fail closed until their owning issue registers and tests an explicit row.
- Domain issues own their services and object/field semantics. #52 and later course/member/export issues consume this cross-cutting contract; they are downstream and must not be made prerequisites that create a cycle.
High-risk contract
Consume #28's approved action classes exactly: staff-role grants, credential creation/rotation, PII exports, content activation, bulk email/event cancellation, grading repair, and certificate mutation require reauthentication plus an action-specific explicit confirmation. Dual approval is absent unless a later owner decision supersedes #28.
The shared policy must define and enforce:
- canonical server-generated action/scope/count/impact/revision preview and digest;
- Studio freshness and reauthentication evidence;
- API-equivalent one-use proof bound to principal, action, scope, count, impact, revision, and idempotency context;
- expiry, replay, mismatch, stale revision, concurrent use, cancellation, policy outage, and unknown-action behavior;
- human versus service-principal eligibility and any exact deny-by-default exception;
- no business mutation, secret generation, idempotency acquisition, or durable side effect before policy authorization; and
- redacted allowed/denied/stale/replayed/conflicted/failed/cancelled audit outcomes.
Credential lifecycle transport remains #33. #32 supplies the provider-neutral policy interface that #33 consumes and does not depend on #33.
Audit, privacy, and production administration
- Audit browse/export remains separately permissioned, object/field scoped, bounded, formula-safe, re-redacted, retention-aware, and free of credentials, tokens, bodies, raw URL/query/header/IP data, provider payloads, reversible identifiers, and unnecessary PII.
- Audit/export failures are safe and do not produce unaudited business state.
- All Studio/admin/private responses are private/no-store/noindex and protected by the accepted zero-TTL edge classification.
- Production Django admin remains disabled; no separate break-glass workflow is introduced.
Owner decisions still required before remaining-scope engineering
#20 and #28 resolved direction but did not approve these security-relevant values. An authorized product/security owner must record exact choices before the remaining complete-issue lane starts:
- Studio high-risk freshness duration and exact reauthentication evidence/refresh behavior.
- Admin-API proof issuer/interface, TTL, one-use persistence, binding fields, replay/concurrency behavior, and service-principal eligibility.
- The bounded code-owned operator reason vocabulary and whether any optional note is allowed. Free-form PII must not enter audit, idempotency, logs, metrics, traces, or retained evidence.
Keep the decision label until these values are accepted. #61's separate admission/session/environment decisions remain owned by #61.
Complete-issue dependencies and downstream work
Required before complete #32 acceptance:
- the owner decisions immediately above;
- an accepted, integrated, on-call-green #61 automated identity/session handoff;
- the reconstructed accepted-slices commit on the same green lineage; and
- accepted secret-free external MFA evidence before any production-ready/closure claim.
Downstream consumers:
- #33 consumes the complete high-risk/API-proof and identity handoffs;
- #52 consumes the global role/function/object/field contract for course-scoped authorization;
- #245 and #250 remain
needs groomingand consume accepted #32/#33 policy symbols later; - #63 performs final residual traceability only after #32/#33/#52 and its other prerequisites;
- #265 follows the bounded #32 integration outcome because of shared settings/bootstrap files.
Complete-issue acceptance criteria
- The accepted #61 identity/session handoff is consumed through accounts-owned local identity and safe session evidence; offboarding/revocation/expiry deny on the accepted bound and raw provider material never crosses the boundary.
- Every management capability available at the frozen baseline has one explicit role/function/object/field/high-risk/audit/concurrency/idempotency/rate/owner row, and unknown/future behavior fails closed.
- Role grants and every #28 action class enforce the exact accepted Studio freshness and API-equivalent proof/confirmation contract, including preview binding, stale/mismatch/replay/concurrency/cancel/outage behavior and no pre-authorization side effects.
- The approved no-dual-approval choice is encoded; any later exception requires a new owner decision and review trigger.
- Audit browse/export is separately permissioned, bounded, formula-neutralized, comprehensively redacted, retention-aware, and safe under corrupt replay, denial, expiry, and actor deletion.
- Production Django admin remains fail-closed and the #20 management-API/direct-database recovery boundary is not weakened.
- Focused and graph-selected Django/PostgreSQL, security/privacy, migration, compatibility, OpenAPI/parity, accessibility, full Playwright, container, and artifact-canary gates pass on one frozen current-main candidate with no unexplained skip.
- A separate tester validates every criterion and opens every required desktop/mobile screenshot; PM accepts the exact candidate before commit.
- Required secret-free external MFA evidence is accepted before #32 is closed or described as production-ready.
Required Django, API, and concurrency scenarios
- Positive/negative/composed-role matrix for every frozen capability, object scope, sensitive field, inactive/revoked/expired staff/session, offboarding, permission change, unknown capability, and no-existence behavior.
- Each #28 action class with fresh/stale/absent authentication, confirm/cancel, valid/expired/replayed/mismatched API proof, changed scope/count/impact/revision/idempotency binding, concurrent use, policy outage, and unknown class.
- Role replacement with exact/changed replay, stale revision, concurrent grant/revoke, target loss, unrelated-group preservation, over-100 target behavior, audit failure, and safe denial.
- Audit browse/export allow/deny, exact/changed replay, filter/row/byte/decompression bounds, formula payloads, prohibited aliases at every depth, corrupt/expired replay, retention cleanup, actor deletion, and no sensitive artifact leakage.
- Production-settings and resolver checks for every
/adminpath form before public catch-alls, plus explicit local/development/test availability.
Browser and screenshot scenarios
With synthetic identities only, at approximately 1440×900 and 390×844:
- Verify role list, review, replace, success, validation, stale-auth, stale-revision, denial, target loss, and target-bound states with keyboard/focus/reflow checks.
- Verify audit filters/detail/export review, empty/over-limit, stale-auth, cancel, conflict, safe failure, replay/download, and private-cache behavior.
- Verify logout/revocation/back-forward cannot recover Studio data.
- Verify allowed navigation/actions appear only for the effective role. Do not capture credentials, emails, reason text, provider values, audit payloads, or production data.
- Preserve the approved public headings
EventsandCommunity knowledgebase; they are not #32 regressions.
Explicit non-goals
- No OIDC protocol/provider/client/MFA implementation or provider/AWS/production mutation.
- No production identity, credential, database, audit, or registration-data access.
- No API credential lifecycle transport/OpenAPI completion (#33), course-scoped assignment/token migration (#52), domain CRUD, or future capability registration.
- No dedicated break-glass credential, production Django-admin workflow, unrestricted impersonation, wildcard scope, or authorization inferred from editorial identity.
- No unrelated public redesign, heading rollback, source pin change, commit, push, merge, deployment, or lifecycle shortcut during grooming/reconstruction.
Delivery convention
Follow _docs/PROCESS.md.
- The reconstructed three-slice commit uses
Refs #32and leaves the issue open. - A later complete-issue commit uses
Closes #32only when every automated criterion and the required external MFA criterion are accepted. If external verification remains pending, useRefs #32, addhuman, name the exact check/owner, and leave the issue open. - Engineer work remains uncommitted until a separate tester passes and PM accepts. The orchestrator then performs the local
--no-ffmerge/push and dispatches on-call. No pull request is created.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read specs 06, 07, and 10 together with resolved decisions #20 and #28, then inspect the accepted #61 identity/session handoff. Do not begin reconstruction until release recovery provides a green current-main base and the three outstanding owner decisions are recorded. Done requires the explicit role, high-risk, audit/export, identity, and production-admin contract to be implemented and verified without treating the preserved old worktree as source.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, playwright, python
- Domain
- authentication, authorization, backend-api-design, security, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 15/100