Skip to main content
This policy operates alongside Authentication (how we verify identity). This page covers authorization — who gets access to what, for how long, and how we verify it stays correct.
Owner: Security Officer · Implementation owner: CTO · Policy version: 0.9 (draft)

Principles

Least privilege

Every identity gets the minimum permissions needed to perform its role. Permissions are additive and opt-in, not stripped-down from a broad default.

Role-based

Permissions attach to roles, not individuals. Individuals inherit permissions via role assignment.

Separation of duties

Critical operations require two independent actors (e.g. deploy + approval; policy change + security officer sign-off).

Periodic review

Access isn’t fire-and-forget. Every access grant is reviewed on a defined cadence; unused grants are revoked.

Just-in-time for privileged access

Privileged operations (prod database read, secret rotation) use time-limited elevation rather than persistent grants.

Audit by default

Every grant, revocation, and use of privileged access is audit-logged for 7 years.

Identity types

Identity typeExamplesHow it authenticates
Customer userBilling staff, provider, practice adminPassword + 2FA (TOTP/passkey), OAuth, or SAML SSO
Denialbase workforceEmployee, contractorSSO via Google Workspace + enforced 2FA
Service account (runtime)Cloud Run backend, worker VMGCP IAM binding + Workload Identity (no long-lived keys)
CI/CD identityGitHub Actions deploy workflowsWorkload Identity Federation (short-lived OIDC → GCP token exchange)
API tokenServer-to-server integrationsScoped, revocable, time-bound token (see Authentication — API tokens)

Customer-side access control

Five roles (see Admins — team management):
RolePHI access
userOwn work, within assigned queues
analystAggregated/anonymized only
supportRead-only, scoped
adminFull within org, no delete
(Denialbase internal) super_adminFull platform, heavily audited
Every API action is authorized by a Pundit policy (48 policy files as of April 2026). ApplicationController enforces after_action :verify_authorized globally — any action that doesn’t authorize or skip raises.
Every PHI-bearing row carries an organization_id. Pundit policies scope queries to the caller’s organization by default. Cross-tenant access requires an explicit super-admin policy and is audit-logged.
30-minute idle timeout; 24-hour maximum session. Configurable per org.

Workforce-side access control

Standard access

Granted on hire based on role. Reviewed quarterly.
SystemRole-based defaults
GitHubDevelopers: write to denialbase repo; others: none
Google WorkspaceEmail, Drive, Calendar for all
GCP (staging)Developers: view; operations: write
GCP (production)No direct access by default; just-in-time only
1PasswordShared vaults by role
SentryEngineering: access to error events
Customer admin UISupport + ops: read-only, scoped, ticketed

Privileged access

Production data access is just-in-time:
1

Request

Engineer or operator opens a break-glass request with: reason, ticket link, scope (what data), duration (≤ 4 hours by default).
2

Approve

Approver (CTO or Security Officer) reviews. Approval is logged.
3

Elevate

IAM binding is created with a time-limited expiry.
4

Use

All actions in the elevated session are audit-logged with the break-glass ticket reference.
5

Expire

IAM binding auto-expires. Post-action summary filed within 24 hours.
Sev-1 incidents may trigger emergency elevation; all emergency uses are reviewed in the subsequent incident post-mortem and management review.

Segregation of duties (A.5.3)

ActivitySeparated
Deploy code to prodCI/CD pipeline (not any individual engineer)
Approve a PRAuthor ≠ reviewer
Change an Annex A controlSecurity Officer + one other executive
Rotate encryption keysCTO proposes + Security Officer approves + independent reviewer verifies
Modify audit log retentionSecurity Officer + CTO; any change audit-logged in a higher-tier log

Service account access control

  • Minimum privilege per service account — Cloud Run runtime SA has access only to the secrets and resources it needs at runtime.
  • No long-lived keys — Workload Identity Federation for CI/CD, Workload Identity (in-cluster) for service-to-service.
  • Annual review of service account IAM bindings as part of internal audit.
  • Automatic revocation of unused service accounts (90-day idle threshold).

Access review (A.5.18)

Quarterly access reviews are a top audit focus. We don’t skip them.
Review typeFrequencyWho performsArtifact
Standard user accessQuarterlyEngineering manager (per report)Signed review record
Privileged accessMonthlySecurity OfficerReview record
Service account IAMQuarterlyCTOReview record
Customer-admin UI grants (support)QuarterlyHead of SupportReview record
Third-party tool grants (Sentry, Slack, GitHub orgs)QuarterlySecurity OfficerReview record
Post-offboardingWithin 1 business day of terminationSecurity OfficerConfirmation logged in HR record
Post-role-changeWithin 1 business day of effective dateSecurity OfficerConfirmation logged in HR record
Unused grants are revoked in the review; exceptions require documented business justification with an expiry.

Password and credential hygiene

  • Passwords must meet the complexity rules defined in the AUP.
  • 1Password is provided and required — no reuse, no local storage in plaintext.
  • MFA required on every account with production-adjacent access.
  • No shared credentials for any system (exceptions documented).

Emergency / break-glass access

For production incidents:
  • A pre-approved break-glass role exists that grants broad access for a 4-hour window.
  • Granted by the Security Officer (or CTO if SO unreachable).
  • Use is written up within 24 hours in the incident post-mortem.
  • Reviewed at the next management review.

Failure to comply

  • First-time minor violations: retraining.
  • Repeat or material violations: discipline per AUP enforcement.
  • Willful breaches involving PHI: termination + referral as required by law.