aps-agent/docs/architecture/auth-tenancy.md

5.9 KiB

Authentication, tenancy, and project collaboration

Security boundaries

  • Every /api/* route is authenticated except health and the authentication handshake.
  • tenant_uuid and user_id are taken only from the verified server-side identity context.
  • Personal sessions are authorized by (tenant_uuid, owner_user_id).
  • Project sessions, files, and scheduling state are authorized through aps_project_members.
  • Tenant-scoped world, checkpoint, knowledge, embedding, preference, and report files use namespaced paths.
  • Cross-boundary resource lookups return 404 where practical so callers cannot enumerate resources.
  • Web credentials and desktop-license credentials use separate HttpOnly cookies and cannot substitute for each other.

Authentication providers

APS_AUTH_PROVIDER=jms enables the real JMS account/password flow. The server calls login precheck, captcha, login, profile, tenant, and logout endpoints at JMS_AUTH_BASE_URL. The browser submits a hand-typed enterprise name (no public tenant list — that API was removed to avoid leaking tenant directory). The server maps known aliases (e.g. 平台 → platform), forwards name/code to JMS login, then revalidates the authenticated tenant from JMS before binding identity. Optional JMS_AUTH_TENANT_CODE / JMS_AUTH_TENANT_NAME can lock the deployment to one tenant. unconfigured keeps every business API closed.

The JMS authentication adapter implements these operations:

login precheck / captcha
login (tenant name typed by user; no public tenant discovery)
authenticate via profile + tenant revalidation
local session refresh
remote logout

User-directory search remains closed with AUTH_USER_DIRECTORY_NOT_CONFIGURED until the user-management scope is integrated. The current JMS OpenAPI has no self-registration or unauthenticated self-service password-recovery endpoint. Account creation and password reset remain enterprise-admin workflows.

The normalized identity is:

user_id, username, fullname, tenant_uuid, roles, expires_at

The external adapter must reject deleted or disabled users and tenants. Client-supplied tenant or user identifiers are never used as authorization input.

Desktop license provider

Electron clients do not show account or phone login. A stable installation UUID is stored in ~/.aps/device-id; an authorization code is activated through POST /api/auth/license/activate and bound to that installation. The server records only hashes of the code and device identifier.

APS_LICENSE_PROVIDER=unconfigured is the production-safe default. APS_LICENSE_PROVIDER=mock is development-only and includes hour, day, week, month, year, and permanent demo grants. Demo code strings are reusable across developer installations, but every resulting activation remains device-bound. License duration is determined by the validated code, never by a client-side selection. Every desktop business request revalidates the activation row, device binding, status, revocation state, and expiry.

The temporary desktop identity derives a stable user_id from the installation UUID so personal projects and sessions retain (tenant_uuid, owner_user_id) isolation. The real license service adapter must return the authoritative tenant and licensed seat identity.

The external license integration must implement:

activate / validate_code
authenticate / validate_activation
refresh
logout
revocation and expiry lookup

Project roles

Action owner editor viewer
Read project, chat, files, schedule yes yes yes
Edit data and run scheduling yes yes no
Add project sessions and files yes yes no
Manage members and delete project yes no no

A project starts with one owner membership. Sharing adds a membership in the same tenant; it never copies project data. Personal sessions remain private even when the same user also belongs to shared projects.

Storage model

  • aps_workspace_projects: project owner and collaborative data version.
  • aps_project_members: tenant-local project ACL.
  • aps_user_workspaces: per-user active project and session.
  • aps_chat_sessions and aps_chat_messages: personal/project scoped conversations.
  • aps_project_files: project asset metadata.
  • aps_schedule_runs and aps_schedule_results: scheduling execution/version records.
  • aps_audit_events: actor, tenant, project, action, and resource audit trail.
  • aps_license_activations: hashed authorization-code binding, device owner, duration, expiry, and revocation state.

Existing master-data tables include tenant_uuid; platform routing templates use the explicit platform tenant and are read-only to normal tenants.

Database rollout

New databases use Alembic revisions 20260727_01 and 20260728_02. Existing SQLite development databases receive compatibility columns at startup. Production MySQL upgrades must be tested on a copy, and existing rows must be mapped to an explicit tenant and owner before constraints are made authoritative.

Recommended cutover:

  1. Back up the database and JSON storage.
  2. Map every historical project to a tenant and owner.
  3. Run alembic upgrade head for a new APS schema, or apply a reviewed delta migration.
  4. Import project, session, message, file, and world data.
  5. Verify row counts, tenant assignments, and project memberships.
  6. Enable the external auth provider and run the isolation test suite.
  7. Keep old JSON data read-only during the rollback window.

External API mapping checklist

  • Login request and response fields.
  • Token verification or introspection endpoint.
  • Cookie/Bearer transport, expiry, refresh, and revocation behavior.
  • User and tenant state fields and deletion semantics.
  • Tenant-local user search endpoint.
  • Role/permission claims and MFA or forced-password-change responses.
  • License-code validation response, duration units, tenant/seat mapping, device limits, revocation, and offline grace policy.