F-011 Client Review Access
| Attribute | Value |
|---|---|
| Project | Open Projects Hub |
| Version | 2.0 |
| Status | Accepted |
| Readiness | Implemented |
| Owner | Product Owner |
Context
- Problem: A freelancer's client needs to confirm that the approved requirements match what they asked for, without being given an account, a password, or access to anything else in the workspace.
- Primary Persona: Client Stakeholder (reviews), Admin and Member (share the access code).
- In Scope: A system-generated Project Access Code per project; a public, read-only Client Review Portal that shows a project's approved user stories for a valid code; regenerating a code to revoke it; rate limiting and uniform not-found responses.
- Out of Scope: Client accounts or logins, per-stakeholder access control or audit, comments or feedback from the client, expiring or signed links, exports from the portal.
Supersedes version 1.x (Viewer Account Management). The invitation-token flow, Viewer accounts, per-project access grants, and the
viewerrole were removed. See ADR-020.
Functional Requirements
| ID | Requirement | Source | Priority | Owner (DRI) | Decision Traceability (Q-ID) | Acceptance Criteria | Status |
|---|---|---|---|---|---|---|---|
| FR-011-01 | Every project has a Project Access Code, generated by the system when the project is created. | Access control baseline | Must | Product Owner | ADR-020 | Format PRJ- plus 8 characters from A-Z and 2-9 without O/I; unique across all workspaces; existing projects are backfilled by migration. | Implemented |
| FR-011-02 | Admin and Member can see a project's access code and a copyable client link. | Admin visibility | Must | Product Owner | — | The project's edit view shows the code and a "Copy client link" action; project list "View" opens the Client Review Portal for that code. | Implemented |
| FR-011-03 | A Stakeholder can open the Client Review Portal with an access code, without an account. | Client access | Must | Product Owner | — | /viewer accepts a code (case and surrounding spaces ignored); /viewer/{code} is a shareable link; no login or token is involved. | Implemented |
| FR-011-04 | The portal shows only the project's approved user stories, read-only. | Access control baseline | Must | Product Owner | — | Shows project name, phase, and each approved story with description and acceptance criteria, highest priority first; drafts never appear; nothing is editable or exportable. | Implemented |
| FR-011-05 | The portal discloses nothing that identifies the workspace, the Client record, or any user. | Data minimisation | Must | Product Owner | — | The response contains no project id or code, client name, creator, or assignee. | Implemented |
| FR-011-06 | Admin and Member can regenerate a project's access code to revoke the previous one. | Access management | Must | Product Owner | — | After confirmation a new code is issued; the old code and any link built from it return "not found" immediately. | Implemented |
| FR-011-07 | An unknown or malformed code returns the same not-found response. | Security baseline | Must | Product Owner | ADR-020 | The API answers 404 Project not found in both cases; the page shows "We couldn't find a project with that access code." | Implemented |
| FR-011-08 | The portal shows a clear empty state when a project has no approved stories yet. | User experience | Should | Product Owner | — | A project with zero approved stories shows an explanatory message rather than a blank page. | Implemented |
Feature-Scoped Non-Functional Requirements
| ID | Requirement | Metric / Target | Priority | Owner (DRI) | Decision Traceability (Q-ID) | Status |
|---|---|---|---|---|---|---|
| NFR-011-01 | Access codes are unguessable. | Generated with a cryptographically secure source; about 10^12 combinations; no sequential or derived component. | Must | Tech Lead | ADR-020 | Implemented |
| NFR-011-02 | The public route is rate limited. | 30 requests per minute per IP, answering 429 beyond that; the limiter's in-memory, per-IP scope is a known limitation. | Must | Tech Lead | ADR-020 | Implemented |
| NFR-011-03 | The public route can read exactly one project, chosen by the code. | The workspace is derived from the project the code resolves to, never from the request; covered by isolation tests. | Must | Tech Lead | — | Implemented |
| NFR-011-04 | The Client Review Portal meets WCAG 2.1 AA. | The form, error messages, and story list are keyboard-navigable and screen-reader compatible. | Should | UI/UX Lead | — | Clarified |
Dependencies and Risks
-
Dependencies:
- F-001 Client and Project Lifecycle Management for the project the code belongs to.
- F-004 Requirements Backlog for the approved stories shown.
- F-003 Access Control and Visibility Boundaries for the Admin and Member roles.
-
Risks:
- Code shared too widely: the code is a bearer secret. Mitigation: regenerate (FR-011-06); the portal is read-only and shows approved stories only.
- Enumeration: mitigation is code entropy (NFR-011-01), uniform 404s (FR-011-07), and rate limiting (NFR-011-02). The limiter is per IP and in memory, so shared storage and forwarded-IP handling are follow-ups.
- No per-person revocation or audit: accepted for MVP; revoking means regenerating for everyone.
Traceability
- Related Architecture/ADR: ADR-020: Client Review by Project Access Code, Security Architecture
- Related Features: F-003: Access Control and Visibility Boundaries, F-004: Requirements Backlog
- Related Prototype: Design Direction
User Experience Flows
Flow 1: Freelancer shares a project with their client
- Admin or Member opens the project's edit view.
- They see the access code and click "Copy client link".
- They send the link or code to their client.
Flow 2: Stakeholder reviews the approved stories
- The Stakeholder opens the link, or goes to
/viewerand types the code. - If the code matches no project: the page shows "We couldn't find a project with that access code." and keeps what they typed.
- If valid: the page shows the project name, phase, and approved stories with their acceptance criteria.
- The Stakeholder tells the freelancer, outside the product, whether it matches what they expected.
Flow 3: Freelancer revokes a code
- Admin or Member opens the project's edit view and clicks "Generate new code".
- A confirmation explains that the current code and any shared link will stop working.
- After confirming, the new code is shown; the old link returns "not found".
Last Updated: 2026-10-02