OpenGranter's service and future management UI use TypeScript. The repository currently implements only the first pure policy-evaluation slice; framework, database, and UI library choices remain open.
- Use Node.js 22 and npm with the committed
package-lock.json. Install withnpm ci. - Use ESM and explicit
.tsextensions for local imports. Import types withimport typeor inlinetypemodifiers. - Keep
strict,noUncheckedIndexedAccess, andexactOptionalPropertyTypesenabled. Do not add broad@ts-ignorecomments or weakentsconfig.jsonto make a change pass. - Use
npm run formatbefore review andnpm run checkas the local and CI gate. Biome owns code formatting and linting; TypeScript owns type checking.
- Keep policy evaluation and other domain rules pure: no database, network, clock, or environment reads in domain functions. Pass required inputs explicitly.
- Validate untrusted HTTP, provider, database, and fixture data at boundaries. Use
unknownuntil validated; avoidanyand unsafe assertions in production code. - Depend on narrow interfaces for secret storage, persistence, identity, and providers so AWS and on-premises adapters can be tested against the same behavior.
- Use descriptive domain names from
CONTEXT.md. UsecamelCasefor values/functions,PascalCasefor types, andkebab-casefor file names. Match external API field names only at adapters. - Prefer small, explicit functions and discriminated unions for expected outcomes. Preserve the cause when rethrowing unexpected failures.
- Never use floating-point arithmetic for billed money. Keep currency, source, and precision explicit; mark estimates as estimates.
- Follow the security invariants in
AGENTS.md. Authentication, authorization, and limits precede any provider call. - Keep secrets and prompt/response content out of normal logs, error objects, and audit-event payloads. Content auditing uses its separate protected store only when enabled.
- Accept provider destinations only from trusted administrator configuration. Never forward a caller-controlled URL.
- Attach a request ID to decisions, usage events, and provider calls; do not treat missing token usage as zero.
- Use TDD for every production-code change. Add a behavior-focused test first, run it to see the expected failure, implement the minimum passing behavior, then refactor with the tests green. Begin a bug fix with a failing regression test. Record the red and green commands and outcomes in the pull request.
- Test behavior through public module boundaries. Run shared cases in
contracts/against the implementation instead of copying the evaluator's logic into tests. - For permission changes, cover implicit Deny, explicit Deny precedence, wildcard matching, inactive principals, and action/resource mismatches.
- For provider and persistence adapters, use fakes for routine tests and focused integration tests for failure paths. Avoid live provider calls in CI.
- Keep tests deterministic: control time, identifiers, and external responses. Do not put real credentials or customer content in fixtures.
- Write or update the issue plan in
docs/plans/before implementation. Update acceptance scenarios and contract cases when product behavior changes; record unresolved product choices as open decisions.