15 KiB
15 KiB
Task: Implement account isolation, roles, and audit
Identity
- Task ID: 20260901-account-system-impl-d4e7a2
- Mode: Feature
- Branch: codex/20260901-account-system-impl-d4e7a2-account-system-impl-d4e7a2
- Worktree: /Users/inmanx/Documents/lwltAPI-account-system-impl-d4e7a2
- Base commit:
ffa3340899 - Owner: codex
- Status: Ready for integration
Scope
- Implement fixed-single-organization
admin,team_lead, anduserroles without adding organization selection or tenant administration. - Add administrator account lifecycle APIs and UI, self-service password change, session revocation, and last-administrator safety.
- Enforce administrator-or-owner authorization for manual tasks, messages, events, artifacts, SSE, and browser execution paths.
- Preserve creator and encrypted initial/supplemental input attribution, expose authorized audit history, and replace routine task deletion with archive/restore.
- Add role-aware operator UI and table-driven security/regression coverage.
- Add a team-lead/administrator-only, read-only operations dashboard for cross-user manual instruction history, work-status summaries, multi-dimensional business drill-through, and “who/instruction/result” detail.
- Add administrator-managed per-account task-type authorization for all 18 registered manual business routes, with server-side fail-closed enforcement and denial audit.
- Do not deploy, restart the existing 8786 service, access the real database/ERP, mutate real runtime tasks, or send data externally. A separately isolated local preview on port 8876 and PostgreSQL port 55432 is permitted by the user's explicit preview request.
Intent And Constraints
- Existing
organization_idremains an internal fixed deployment scope and compatibility boundary; it is not exposed as a product concept. - Existing users migrate as administrators. Administrators always retain all 18 manual business routes. New ordinary users and team leads start with no manual task-type authorization and can operate only explicitly granted routes for tasks they create; AgentBus/system tasks remain administrator-only and keep their separate channel authorization boundary.
- Team leads gain cross-user visibility only through dedicated read-only dashboard APIs. That capability does not extend normal task mutation, artifact download, SSE, ERP execution, account administration, global audit, automation, parser, or AgentBus permissions.
- Authorization is enforced in server/service/database access paths, never only by navigation visibility.
- Unauthorized resource identifiers fail without revealing cross-user existence.
- Initial and supplemental input remain encrypted at rest; password material and raw business input never enter audit or operational logs.
- Organization-wide ERP execution serialization, confirmation, idempotency, uncertain-write, and requery safety gates remain unchanged.
- Routine deletion becomes reversible archive/restore. Physical purge remains unavailable until an explicit retention policy is authorized.
- Task-type authorization is re-read from PostgreSQL at every creation/continuation and before confirmation, automatic confirmation, and browser claim, so revocation takes effect without waiting for session expiry. A non-administrator instruction that cannot resolve to exactly one registered route fails closed.
- The semantics and ERP contracts of the 18 registered business routes remain unchanged; this feature changes only which signed-in accounts may invoke each route.
Permission Contract
| Surface | Administrator | Team lead | Ordinary user |
|---|---|---|---|
| Login, logout, current user, CSRF, own password | Allowed | Allowed | Allowed |
| Account list/create/status/role/reset/session revocation | Allowed | Denied | Denied |
| Manual task-type authorization | All 18 routes, fixed | Explicit administrator grants only; default none | Explicit administrator grants only; default none |
| Automation, parser routing/review/reparse, AgentBus channels, global audit | Allowed | Denied | Denied |
| Normal task list/search/detail/events/input history | All fixed-scope tasks | Own non-AgentBus tasks only | Own non-AgentBus tasks only |
| Create task/message/confirm/claim/result/cancel/archive/restore | Any authorized task | Own task only | Own task only |
| Artifact download and SSE | All fixed-scope tasks | Own task only | Own task only |
| Operations dashboard summaries and user directory | All manual account tasks | Read-only, all manual account tasks | Denied |
| Operations dashboard instruction/attachment-name/business-result detail | Read-only, all manual account tasks | Read-only, all manual account tasks | Denied |
| Browser heartbeat/connection | Own authenticated connection | Own authenticated connection | Own authenticated connection |
| AgentBus/system tasks | Allowed | Not visible | Not visible |
| Physical task purge | Not exposed | Not exposed | Not exposed |
Unauthorized task and artifact identifiers use the existing not-found response to avoid enumeration. Administrator-only settings and account endpoints use an explicit forbidden response.
Outcome
- Added migration
015_account_roles_and_task_audit: existing accounts remain administrators; newadmin/userroles, forced-password lifecycle fields, message/attachment actor attribution, reversible task archive fields, and account-scoped manual idempotency keys are persisted. No organization selector or tenant-management concept was added. - Added migration
016_team_lead_operations_dashboard: the fixed role constraint now acceptsteam_lead, and bounded manual-task indexes support time-, actor-, status-, and business-type-oriented dashboard reads. - Added migration
017_user_business_route_authorizations: durable fixed-scope per-user allowlists cover all 18 registered manual business routes, carry administrator attribution and optimistic authorization revisions, and enforce same-organization user/granter references. Schema readiness now requires migration 017. - Implemented administrator account management for list/create, enable/disable, role changes, password reset, and session revocation. Passwords remain Argon2id hashes, reset accounts can be forced to change password, role/status changes revoke sessions, and self-lockout plus removal of the last active administrator are blocked transactionally.
- Enforced owner-restricted access for both ordinary users and team leads on task list/search/detail, messages, input history, artifacts, lifecycle mutations, browser claim/result, archive/restore, historical events, and live SSE. Both roles can access only their own manual tasks through normal business APIs; AgentBus/system tasks remain administrator-only. Browser connection IDs are user-bound and idempotency keys no longer collide across manual accounts.
- Added authorized creator/original-input audit: task creator, every newly attributed user turn, attachment actor, lifecycle event actor, and account/task audit events are available to the authorized operator. Input contents and file names remain encrypted at rest; passwords and plaintext business input are not copied into the global audit log.
- Replaced routine task deletion with archive/restore across the API, UI, retention job, and compatibility routes. Physical task/audit purge code is no longer exposed or retained in the task service.
- Added role-aware platform pages for account management and global audit, mandatory/self-service password change, administrator-only settings navigation, creator/input history, per-user browser connection identity, and active/archived task views. Administrators can assign the new 组长 role.
- Added an administrator-only task-permission panel in account management with all 18 business types, selected counts, select-all/clear, optimistic save protection, and effective authorization display. Administrators are permanently shown as fully authorized; new non-administrator accounts are clearly created with no task permissions until an administrator grants them.
- Enforced the allowlist in the task service before initial parsing/plugin dispatch, on supplemental messages and passenger attachments, inside creation transactions, before manual and automatic confirmation, and before browser/ERP claim. Confirmation and claim evaluate the task creator rather than the acting administrator, so a revoked creator cannot be bypassed by an administrator. Non-administrators receive
business_not_authorizedfor a known denied route orbusiness_type_unresolvedwhen the route is unknown/non-unique; both paths stop execution and return a business-readable Chinese prompt. Denial audit stores actor, route/revision, phase, and an input hash only—never the plaintext instruction—and explicitly records that parsing, plugin dispatch, and ERP writes did not run. - Added
/operations-dashboardand leadership-gated GET APIs with a default 30-day window, a 366-day maximum, status/person/Shanghai-business-day/business-type drill-through, aggregate KPIs, per-user work summaries, bounded pagination, and on-demand business detail. Keyword query matches the creator, full initial and supplemental instructions, business type, readable business result, task record number, group number, and order number after structured filters; decrypted matching is bounded to 2,000 candidates. Dashboard queries include only manual tasks. Its dedicated list/detail contracts expose only who acted, what was instructed, what business outcome was recorded, business type, timestamps, and simplified input attachment attribution; lifecycle events, parser/executor JSON, technical stages/errors, and artifact access data are not returned. No dashboard mutation route exists. - Updated
control-plane/README.mdto describe the three-role account model, owner isolation, read-only operations dashboard, administrator-managed task-type allowlists, fail-closed enforcement, archive semantics, migrations 015/016/017, and the latest schema readiness gate. - Added table-driven three-role access-policy tests plus migration, authorization-path, dashboard, UI, audit, idempotency, and no-purge regression assertions. The 18 business routes and ERP serialization/write-safety contracts were not changed.
- Upgraded only the isolated local preview on
127.0.0.1:8876: applied migration 017 to its dedicated PostgreSQL database, restarted only the preview process, assigned small demonstrative allowlists to the preview lead/Alice/Bob accounts, and verified a denied instruction did not create a task. The existing service on port 8786 remained on its original PID and was not touched. - No deployment, real-service restart, real database migration, ERP access, real runtime task mutation, secret read, or external message occurred.
Verification
node --run check:repo: 10/10 passed.node --run check: passed.node --run test:control-plane: 153/153 passed.node --run test:legacy: 256/256 passed.node --run build: passed.node --check LianSyn-platform/app.js: passed.git diff --check: passed.- Focused authorization regression (
node --test --import tsx control-plane/test/account-authorization.test.ts control-plane/test/control-plane.test.ts): 60/60 passed. - Disposable PostgreSQL API smoke: new non-administrator denied by default; one granted route accepted; another ungranted route denied; only the authorized task persisted; two denials were durably audited.
- Fresh disposable PostgreSQL migration: migrations 001–017 applied successfully, schema head was
017_user_business_route_authorizations, and the disposable database was removed afterward. - Isolated preview readiness:
/health/readyreported database/schema ready with required migration 017; the account catalog returned all 18 task types; Alice, Bob, and the team lead received 2, 1, and 3 demonstrative grants respectively; Bob's ungranted “安排导游” instruction returned HTTP 403business_not_authorizedwith the expected Chinese prompt. check_project_docs.py: passed.check_doc_drift.py --task-id 20260901-account-system-impl-d4e7a2: passed.
Follow-ups
- Integrate this feature worktree before deployment, then apply migrations
015_account_roles_and_task_audit,016_team_lead_operations_dashboard, and017_user_business_route_authorizationsand restart the control plane only under separate authorization. - In an authorized staging/runtime window, create one team-lead and two ordinary test accounts. Verify forced password change, default-deny task permissions, per-route grant/revoke without re-login, known-route and unresolved-route denial prompts, no parsing/plugin/ERP side effects on denial, creator-based revocation at confirmation/claim, own-task visibility, cross-user 404 behavior on normal task/artifact/SSE paths, AgentBus invisibility, dashboard denial for ordinary users, and team-lead cross-user drill-through by status/person/date/business plus keyword hits in supplemental instructions and completed business results. Also verify the dashboard response contains no lifecycle/parser/executor/artifact-access data, then cover account session revocation, creator/input audit, and archive/restore against PostgreSQL and independent browser sessions.
- Keep physical purge unavailable unless a separately approved retention design defines legal/audit retention periods and privileged irreversible-purge controls.
Promotion Candidates
- Target canonical architecture/security/current-state memory during a later Integration task.
- Proposal: record the fixed-scope account model as
admin,team_lead, anduser, with no product-visible organization concept. Team leads retain ordinary-user ownership boundaries for business operations but receive dedicated cross-user, manual-task-only, read-only operations-dashboard access; administrators retain global settings, AgentBus/system tasks, account lifecycle, and global audit. - Proposal: record the operations dashboard as a business-facing projection rather than a privileged task-debug surface: status/person/Shanghai-day/business drill-through and bounded plaintext matching are permitted, while lifecycle events, parser/executor payloads, technical stages/codes, and artifact access remain outside its response contract.
- Proposal: record creator/input attribution, account-scoped idempotency, user-bound browser connections, forced password change/session revocation, last-administrator protection, and archive/restore as security invariants.
- Proposal: record manual business eligibility as an administrator-managed allowlist over the 18 registered routes: administrators are always fully authorized, team leads/users default to none and require explicit grants, unknown/non-unique routes fail closed, revocation is checked at each state transition, and AgentBus keeps its independent channel boundary.
- Evidence:
control-plane/migrations/015_account_roles_and_task_audit.sql,control-plane/migrations/016_team_lead_operations_dashboard.sql,control-plane/migrations/017_user_business_route_authorizations.sql,control-plane/src/auth.ts,control-plane/src/task-service.ts,control-plane/src/server.ts,LianSyn-platform/index.html,LianSyn-platform/app.js,LianSyn-platform/styles.css,control-plane/README.md, andcontrol-plane/test/account-authorization.test.tsplus the full verification above. - Human confirmation required: already received for the single-organization three-role ownership/audit/dashboard behavior; integration, database migration, deployment, restart, and live smoke testing remain separately authorized.