Document Service — Razorpay Machine Coding Round
Razorpay machine coding round — design a document service with ownership and per-user access control, scoped to an acting user.

Design and implement a simple document service where users can create documents and read them back. A document is just a name paired with string content — the interesting part of this problem is the access-control model layered on top of it.
This one tests whether you can build a correct permission model from scratch — private-by-default documents, owner-granted read/edit access, and an owner-only delete rule — while keeping every operation scoped to "on behalf of" a specific user rather than trusting a global, unscoped action.
Objective
The primary objective is to design and implement a user-scoped document service that supports creating private documents, granting read/edit access, and enforcing owner-only deletion — with correct permission checks on every operation.
Data Model
Each document is conceptually a name paired with its content, owned by the creating user.
Document => <name: string, content: string>
There's no anonymous or unscoped action — create, read, edit, and delete must all be performed on behalf of a specific user. A username is just a plain string; there's no separate user-registration step implied by the source problem.
Functional Requirements
Requirements are split into two tiers so you know what to prioritize under time pressure: build first, and worth proposing if time allows.
Part 1 — Basic Requirements
Core functionality you must build and get working first.
Documents are private at creation — no one but the owner can read or edit a brand-new document. Access is additive and owner-controlled: only the owner can call grant, and only the owner can delete, regardless of what access level anyone else holds. Edit access implies read access, but read access does not imply edit access.
Part 2 — Suggested Extensions
Part 3 — Future Extensions
Example Usage: Full Walkthrough
1. Create a document — private by default
> create("alice", "roadmap", "Q3 goals: ship search v2")
✅ Document 'roadmap' created, owned by alice.
> read("bob", "roadmap")
❌ Access denied. bob has no access to 'roadmap'.
2. Owner grants read access
> grant("alice", "roadmap", "bob", "read")
✅ bob granted READ access to 'roadmap'.
> read("bob", "roadmap")
"Q3 goals: ship search v2"
3. Read-only access does not allow editing
> edit("bob", "roadmap", "Q3 goals: ship search v2 and v3")
❌ bob has READ access only — cannot edit 'roadmap'.
4. Owner grants edit access to someone else
> grant("alice", "roadmap", "carla", "edit")
✅ carla granted EDIT access to 'roadmap'.
> edit("carla", "roadmap", "Q3 goals: ship search v2 and v3")
✅ 'roadmap' updated by carla.
5. Only the owner can delete — even an editor cannot
> delete("carla", "roadmap")
❌ carla is not the owner — cannot delete 'roadmap'.
> delete("alice", "roadmap")
✅ 'roadmap' deleted by alice.
Bob is denied read access until explicitly granted, then correctly blocked from editing since read access doesn't imply edit access. Carla, despite holding edit access, is still blocked from deleting — only alice, the owner, can. This traces the full access hierarchy: private by default, then read, then edit, then owner-only delete.