Files
atelier/domains/security/authorization.md
T
Jon Chery 496303471d docs(milestone): complete v0.1 — initial framework
---ci---
project: atelier
phase: 7
milestone: v0.1
status: complete
phase_role: final
milestone_complete: true
requirements:
  covered: [ATELIER-01, ATELIER-02, ATELIER-03, ATELIER-04, ATELIER-05, ATELIER-06, ATELIER-07, ATELIER-08, ATELIER-09, ATELIER-10, ATELIER-11, ATELIER-12, ATELIER-13, ATELIER-14, ATELIER-15, ATELIER-16, ATELIER-17, ATELIER-18, ATELIER-19, ATELIER-20, ATELIER-21, ATELIER-22, ATELIER-23, ATELIER-24, ATELIER-25, ATELIER-26, ATELIER-27, ATELIER-28, ATELIER-29, ATELIER-30, ATELIER-31, ATELIER-32, ATELIER-33, ATELIER-34, ATELIER-35]
  partial: []
ship:
  milestone: v0.1
  type: NFR
  tag: v0.0.7
  merge: milestone/v0.1-atelier -> main
  release: https://git.cloudinit.dev/cloudinit-bot/atelier/releases/tag/v0.0.7
---/ci---

Milestone v0.1 — Initial Framework (NFR, complete).
8 core principles (C1-C8), 11 domains, 110 domain principles, 27 derived docs, 4 good + 3 bad examples, 4 language docs, full matrix, 3 review docs.
All 35 requirements covered. 7 patches (v0.0.0 pre-execution through v0.0.7 final). v0.0.7 IS the v0.1.0 milestone release.
2026-08-05 00:36:55 +00:00

2.7 KiB

Authorization — Derived Rules

Derives from domains/security/first-principles.md P2 (Least Privilege), P3 (Defense in Depth), P1 (Zero Trust).

The Default: Deny

  • Every request is denied unless explicitly authorized.
  • "Authorized by default" is an anti-pattern. The absence of a rule means denial.
  • A missing authz check is a bug, not a feature gap.

Authorization Models

RBAC (Role-Based)

  • Users have roles; roles have permissions.
  • Roles are coarse: admin, editor, viewer. Permissions are fine: post:create, post:delete.
  • Check permissions, not roles: can(user, 'post:create'), not user.role === 'admin'.
  • Roles can change; permission checks are stable.

ABAC (Attribute-Based)

  • Authorization based on attributes of the user, resource, and context.
  • More expressive: "user can edit a post if user.department == post.department and post.status == 'draft'".
  • Use when RBAC is too coarse. Beware: complex ABAC is hard to audit.

ReBAC (Relationship-Based)

  • Authorization based on relationships (e.g., Zanzibel).
  • "user:alice is editor of document:42" — check the relationship graph.
  • Scales for fine-grained, resource-specific access (Google Docs-style).

Where to Check (P4 Locality)

  • Check at the boundary: the API endpoint, the resolver, the controller.
  • Check at the data layer: defense in depth. A query that bypasses the controller still respects row-level security.
  • Never check only in the UI. The UI is a convenience, not a security boundary.

Principle of Least Privilege (P2)

  • A token/role gets the minimum permissions to do its job.
  • No "admin" role for daily work. Admin is for administration; daily work uses a scoped role.
  • Service tokens are scoped to one service's resources, not "all resources."

IDOR (Insecure Direct Object Reference) (P1 Zero Trust)

  • /api/users/123 — does the requester own 123? Check.
  • Never assume the user can access any ID they request. The ID is input; inputs are untrusted.
  • Use scoped queries: User.find({ id, owner: userId }), not User.find(id).

Caching and Authz (P3 Defense in Depth)

  • Authorization is not cached across users. A cached response for user A is not served to user B.
  • Cache keys include the user/role, not just the resource.
  • "Cache it as public if anyone can see it" — only if truly anyone (no auth).

What Violates Authorization

Violation Principle
/admin endpoint with no authz check P1 Zero Trust
user.role === 'admin' instead of permission check P2 (roles change)
IDOR: User.find(req.params.id) with no ownership check P1 Zero Trust
Cached authz decision reused across users P3 Defense in Depth
Service token with "all resources" scope P2 Least Privilege