Documentation as a First-Class Citizen & Planning Standards

ON THIS PAGE

In a traditional software organization, documentation is often treated as an afterthought—written right before a release or skipped entirely due to time constraints. In an AI-augmented enterprise, outdated or missing documentation is an outage waiting to happen. AI agents do not have "tribal knowledge" or institutional memory; they rely strictly on the context provided in repository files, API schemas, design docs, and ticket descriptions. If documentation is ambiguous, incomplete, or wrong, agents will produce hallucinated architectures, violate domain boundaries, and break production.

Documentation must be treated as a first-class citizen, held to the exact same quality and review standards as production code.

1. System-Level Documentation (Outside of Code) #

System-level documentation establishes the architectural boundaries, business rules, and design trade-offs before a single line of code is written.

A. Ubiquitous Domain Glossary (GLOSSARY.md) #

To prevent semantic ambiguity across frontend, backend, database, and prompt layers, every repository must maintain a root-level GLOSSARY.md file. Terms must have a single, canonical definition across all systems.

markdown
# Domain Glossary

### Active User
A user account with status = 'ACTIVE' that has authenticated within the last 30 rolling days. 
* Anti-Pattern: Do not confuse with "Registered User" (created account but may never have logged in) or "Subscribed User" (has an active billing plan).

### Organization Tenant
A top-level entity (tenant_id) representing an enterprise client. All database queries for multi-tenant data MUST include WHERE tenant_id = :tenant_id.

### TOTP (Time-Based One-Time Password)
A 6-digit cryptographic code generated by an authenticator application (RFC 6238) valid for a 30-second window.

B. AI-Ready Product Requirement Documents (PRDs) #

PRDs translate raw product ideation and stakeholder interviews into structured, machine-readable specifications. PRDs live in the repository under /docs/prds/ or are linked directly in Azure DevOps Epics/Features.

  • Problem Statement & Business Goal: Clear, quantitative outcome statement.

  • User Personas & Flows: Step-by-step user interaction journey.

  • Functional Requirements: BDD-style functional requirement statements.

  • Non-Functional Requirements: Performance SLAs, security boundaries, and rate limits.

  • Data & Schema Impact: New database entities or field migration requirements.

C. Architecture Decision Records (ADRs) #

ADRs capture why architectural decisions were made, what alternatives were evaluated, and what trade-offs were accepted. Without ADRs, AI agents (and human engineers) will routinely propose refactoring code back into an anti-pattern that was intentionally discarded six months prior.

ADRs live in /docs/adr/000X-short-title.md.

markdown
# ADR 0003: Use Redis Sliding-Window for TOTP Rate Limiting

* Status: Accepted
* Date: 2026-07-21
* Deciders: Principal Architect, Lead Security Engineer

## Context
To prevent brute-force attacks on our 6-digit TOTP authentication endpoint (/api/v1/auth/mfa/verify), we must enforce strict rate limiting (max 5 failed attempts per user per 15-minute window).

## Considered Options
1. PostgreSQL Database Lookup: Querying failed_attempts table on every login request.
2. In-Memory Local App Cache (Node.js Memory): Tracking attempts in process memory.
3. Redis Sorted Set (ZSET) Sliding-Window: Distributed rate-limiting counter in Redis.

## Decision
We chose Option 3 (Redis Sorted Set) because:
* PostgreSQL queries under high authentication load introduce unacceptable DB lock latency.
* In-memory local app cache fails in horizontally scaled multi-pod Kubernetes deployments because requests are round-robined across pods.

## Consequences
* Positive: Atomic, distributed rate-limiting across all app instances with sub-millisecond response latency.
* Negative: Introduces a dependency on the Redis cluster. If Redis goes down, authentication falls back to fail-closed state.

D. Schema-First API Contracts #

Never let an agent infer API shapes from implementation code. Define OpenAPI (Swagger) or Protocol Buffer contracts before writing frontend or backend code.

  • Location: /docs/api/openapi.yaml

  • Rule: Frontend and backend code generators must bind to this file. Changes to endpoints must happen in openapi.yaml first.

2. Code-Level Documentation Standards #

Code-level documentation explains the intent, logic boundaries, and assumptions of individual modules.

A. Self-Documenting Code vs. Explanatory Comments #

  • Code describes WHAT and HOW: Clean variable naming, modular functions, and strong type annotations reduce redundant noise.

  • Comments describe WHY: Comments should explain non-obvious business rules, workaround hacks, or performance trade-offs.

typescript
// BAD COMMENT: Explaining what the code clearly already says
// Increment count by 1
count = count + 1;

// BAD COMMENT: Fetch user from database
const user = await db.users.findById(id);

// GOOD COMMENT: Explaining the "WHY", business rules, or non-obvious constraints
// We enforce a 30-second clock skew tolerance window to account for drift 
// between client authenticator devices and our NTP servers (RFC 6238 section 5.2).
const isTotpValid = totp.verify({
  token: userProvidedCode,
  secret: userMfaSecret,
  window: 1 // +/- 30 seconds
});

B. Standardized Module & Function Docstrings #

All exported functions, types, and classes must include structured docstrings (TSDoc, JSDoc, Python Docstrings).

typescript
/**
 * Verifies a time-based one-time password (TOTP) against a user's encrypted secret.
 *
 * @param userId - Unique UUID of the user attempting verification.
 * @param token - 6-digit numeric string provided by the user.
 * @returns Promise resolving to `true` if valid, or `false` if expired/incorrect.
 * 
 * @throws {@link RateLimitExceededException} If user has exceeded 5 failed attempts in 15 mins.
 * @throws {@link UserNotFoundException} If user ID does not exist in active database.
 * 
 * @example
 * const isValid = await verifyTotpToken("usr_992a", "123456");
 */
export async function verifyTotpToken(userId: string, token: string): Promise<boolean> {
  // Implementation
}

C. Commit Messages & PR Descriptions #

Commits and Pull Requests are historical documentation. Every commit and PR must follow conventional formats linked directly to Azure DevOps work items.

text
feat(auth): add Redis sliding-window rate limiting for TOTP verification [AB#10820]

- Implement Redis Sorted Set counter in rateLimiter.ts
- Add unit tests verifying 5-attempt limit and 15-min expiry window
- Update openapi.yaml to include HTTP 429 response schema

Closes AB#10820

3. Mandatory Execution Rules for Engineers & AI Agents #

To ensure documentation remains accurate over time, human developers and AI agents must follow these explicit rules while working on a ticket:

  • Rule 1: The Atomic PR Rule (Code + Docs in One PR): If a PR modifies function signatures, API schemas, or environment variables, the corresponding documentation (openapi.yaml, README.md, or docstrings) must be updated inside the exact same PR. CI gates will reject PRs if API schemas or export signatures are altered without doc updates.

  • Rule 2: Continuous In-Flight Work Logging: Before writing code, engineers or agents must post an implementation plan as a comment on the Azure DevOps ticket. If an unexpected technical blocker changes the approach mid-task, add a comment explaining the pivot before proceeding.

  • Rule 3: The ADR Trigger: If an engineer or agent makes an architectural choice that introduces a new dependency, alters a data model, or impacts system security, an ADR must be drafted under /docs/adr/ as part of that ticket.

3. AI-Readable Documentation Principles #

Human engineers skim documentation looking for highlights and diagrams; AI agents parse documentation line-by-line looking for deterministic rules, exact types, and boundary conditions. To ensure your documentation serves both audiences effectively, follow these core principles:

  • Semantic Heading Hierarchies: Use strict, nested Markdown headers (#, ##, ###). Agents use heading trees to construct mental maps of document structure. Never skip heading levels (e.g., # directly to ###).
  • Explicit Code Signature Block: Include complete, runnable code signatures with types rather than pseudocode snippets. An agent reading a TypeScript signature with explicit Promise<Result<User, AuthError>> learns the exact contract; pseudocode forces it to guess.
  • Negative Constraints ("What NOT to do"): Agents respond exceptionally well to negative constraints ("Anti-Pattern", "Never do X"). Express hard boundaries explicitly rather than implying them.
  • Single Source of Truth Links: Cross-reference related docs using relative file paths ([ADR 0003](../adr/0003-redis-rate-limiting.md)) so agents using file-navigation tools can trace decision graphs independently.

4. Documentation Do's and Don'ts Matrix #

AreaDO ✅DON'T ❌
System TermsMaintain a single GLOSSARY.md file for domain entity definitions.Allow "User", "Account", and "Member" to be used interchangeably without definition.
Code CommentsComment on why a complex workaround or security window exists.Comment on obvious code operations (e.g., // increment i by 1).
API DesignWrite OpenAPI/Swagger specs before writing backend/frontend code.Build API routes first and try to auto-generate docs from messy code later.
Pull RequestsUpdate code, docstrings, and design docs together in a single atomic PR.Merge code changes with a promise to "update the docs next week".
ArchitectureRecord trade-offs and discarded options in ADR files.Rely on private chats or meetings to decide architectural direction.
Ticket WritingUse BDD Given / When / Then syntax in Azure DevOps acceptance criteria.Write vague bullet points like "Fix authentication page bugs".