Access Control Policy¶
| Field | Value |
|---|---|
| Status | draft |
| Owner | INFRA (application authz) / DIR (account & infra access) |
| Applies to | End-user access to the application; operator/contributor access to source, cloud, vendor consoles, and the data room; service-to-service access (DB, Redis, LinkedIn). |
| Review cadence | Annual; access list reviewed quarterly via ../procedures/access-review-procedure.md; on every onboarding/offboarding. |
| Mapped controls | SEC-01 (session tokens), SEC-02/03 (OAuth/handoff), SEC-04 (object-level authz), SEC-12 (session lifecycle). |
| Evidence | partile-infra: app/auth/tokens.py, app/auth/state_store.py, app/auth/handoff_store.py, repositories/conversations.py, repositories/matches.py; readiness/threat-model-and-auth-review.md. |
| Exception handling | Temporary elevated access is time-boxed and logged by DIR; recorded in the access review. |
Purpose¶
Ensure only the right identities reach the right data, at the application, infrastructure, and human levels — least privilege by default.
Application access (end users)¶
- Identity is LinkedIn OIDC; Partile stores only
sub, email, name, picture. - Sessions use opaque high-entropy tokens stored only as SHA-256 hashes; plaintext is returned to the client once and never persisted (SEC-01).
- OAuth CSRF state is single-use (atomic GETDEL, short TTL); the mobile handoff uses one-time codes with no token in any URL and a fixed redirect target — no open-redirect surface (SEC-02, SEC-03).
- Object-level authorization is enforced in SQL, not only at routes:
non-visible objects return 404 with no existence leak (SEC-04). A cross-user
IDOR regression test is required in CI (SEC-15,
not started). - Block separation is an access rule: block-separated users cannot match, surface, or (when built) message — enforced at every read/derive path (SAF-01).
- Session lifecycle: 14-day TTL today; expired/revoked rows are swept
(SEC-12). Idle timeout + rotation is an open gap (
designed, M3).
Human / operator access¶
- Least privilege, role-based. Roles: DIR, INFRA, OPS, MOBILE, COUNSEL. Today the operator holds most; the role split is enforced as people are added.
- Cloud/vendor consoles (Google Cloud, Apple, Cloudflare, LinkedIn developer, GitHub; AWS only if superseded evidence or a future reintroduction requires it): access is per-role, MFA required where the provider supports it, and listed in the access review. Account IDs and credentials are Tier 2 (never in repo).
- Source & data room: contributors access via GitHub with reviewed-PR merge
to
main; no direct pushes that bypass review (change-management-policy.md). - Service credentials (DB, Redis, vendor keys) are least-privilege and stored
in GCP Secret Manager / operator secret stores, not in code
(
cryptography-and-secrets-policy.md).
Joiners / movers / leavers¶
Provisioning and de-provisioning follow
../procedures/onboarding-offboarding-procedure.md: access granted per role on
join, adjusted on role change, and revoked promptly on leave (sessions
revoked, console access removed, secrets rotated if exposed).
Review¶
Access is reviewed quarterly (../procedures/access-review-procedure.md):
confirm each human identity still needs each grant, MFA is on, and no orphaned or
shared accounts exist. The review date feeds SEC-12 / GOV-01.
Exceptions¶
Break-glass or temporary elevation is time-boxed, justified, and recorded by DIR in the access review log; it is removed at expiry. Any exception is noted on the relevant control row.