Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
e6800db
fix(iam): compare bootstrap rows by owned fields
BeforeLights Aug 2, 2026
b7ee10a
perf(iam): bound membership reads to organization scope
BeforeLights Aug 2, 2026
26ff403
fix(iam): make membership selection deterministic
BeforeLights Aug 2, 2026
587eebe
fix(iam): expire in-memory access tokens
BeforeLights Aug 2, 2026
e668bd4
fix(iam): compare-and-set MFA revisions
BeforeLights Aug 2, 2026
6d26ec7
fix(iam): use constant-time recovery matching
BeforeLights Aug 2, 2026
a62e515
fix(iam): map session persistence failures to unavailable
BeforeLights Aug 2, 2026
8ea5ec9
fix(http): require production CSRF origins
BeforeLights Aug 2, 2026
8874b36
perf(aud): scope chain reads to the target ledger
BeforeLights Aug 2, 2026
463abbb
fix(aud): compare immutable records by owned fields
BeforeLights Aug 2, 2026
eb02077
fix(bua): compare immutable records by owned fields
BeforeLights Aug 3, 2026
ebe73cf
perf(aud): bound append lookups to latest and replay
BeforeLights Aug 3, 2026
bb8a11f
perf(bua): scope usage reads to tenant ancestry
BeforeLights Aug 3, 2026
50e325d
fix(bua): enforce terminal reservation transitions
BeforeLights Aug 3, 2026
2328dd4
fix(bua): return entitlement problems with HTTP status
BeforeLights Aug 3, 2026
295b911
fix(iam): authorize sign-out session ownership
BeforeLights Aug 3, 2026
afdd94b
fix(iam): map MFA persistence failures to unavailable
BeforeLights Aug 3, 2026
5e67f8b
fix(iam): fail closed at device identity API boundary
BeforeLights Aug 3, 2026
7c94a11
fix(iam): distinguish session authority outages
BeforeLights Aug 3, 2026
44c1fae
test(iam): exercise unsafe principal rejection
BeforeLights Aug 3, 2026
868267d
fix(iam): bound session cookie parsing
BeforeLights Aug 3, 2026
447b029
fix(http): bound CSRF cookie parsing
BeforeLights Aug 3, 2026
048d5bd
fix(iam): enforce narrowest membership authority
BeforeLights Aug 3, 2026
c48aa8b
fix(iam): scope membership mutation lookup
BeforeLights Aug 3, 2026
4f1b555
fix(iam): scope device identity lookups
BeforeLights Aug 3, 2026
ead1d27
fix(aud): map read outages to unavailable
BeforeLights Aug 3, 2026
ab1e2a6
fix(aud): scope event identity lookup
BeforeLights Aug 3, 2026
e86f7ad
fix(bua): scope entitlement identity lookups
BeforeLights Aug 3, 2026
784fa32
fix(iam): propagate session authority outages
BeforeLights Aug 3, 2026
7b628f2
fix(iam): bind sessions to tenant scope
BeforeLights Aug 3, 2026
12b8c3a
docs(traceability): reconcile identity foundation coverage
BeforeLights Aug 3, 2026
2c12a91
docs(git): enforce 30 to 50 commit PR slices
BeforeLights Aug 3, 2026
8e9d753
style(iam): format bootstrap repository
BeforeLights Aug 3, 2026
47db553
test(api): register session scope migration
BeforeLights Aug 3, 2026
d323c02
test(web): tolerate lazy route startup under load
BeforeLights Aug 3, 2026
5d09843
fix(aud): preserve success responses in OpenAPI
BeforeLights Aug 3, 2026
7ccbbd1
Merge pull request #28 from DatabreezeService/feat/foundation-identit…
BeforeLights Aug 3, 2026
ccbb9d3
fix(bua): preserve project usage scopes
BeforeLights Aug 3, 2026
a8a5a47
fix(bua): transact direct usage persistence
BeforeLights Aug 3, 2026
0615d54
fix(http): accept standard cookie names
BeforeLights Aug 3, 2026
1bf5650
fix(iam): compose database session context
BeforeLights Aug 3, 2026
66a9a56
fix(iam): require proof before MFA activation
BeforeLights Aug 3, 2026
774d4d5
fix(iam): derive MFA timestamps from server clock
BeforeLights Aug 3, 2026
85d60cc
fix(http): require mutation idempotency keys
BeforeLights Aug 3, 2026
cf47989
fix(iam): fail closed on missing active refresh token
BeforeLights Aug 3, 2026
a5478ae
fix(iam): enforce session inactivity on refresh
BeforeLights Aug 3, 2026
0483b4b
fix(api): expose native refresh response tokens
BeforeLights Aug 3, 2026
d83eeb9
fix(iam): type transaction-scoped membership clients
BeforeLights Aug 3, 2026
222910a
fix(iam): resolve personal bootstrap deterministically
BeforeLights Aug 3, 2026
a5ba31b
feat(aud): verify independently paged event digests
BeforeLights Aug 3, 2026
72064d6
feat(aud): bind opaque page cursors to tenant scope
BeforeLights Aug 3, 2026
bbca81c
feat(aud): paginate public audit reads
BeforeLights Aug 3, 2026
259c92a
fix(iam): skip malformed membership read rows
BeforeLights Aug 3, 2026
21eb825
test(api): require bearer security on protected operations
BeforeLights Aug 3, 2026
a17772f
docs(review): record PR 29 dispositions
BeforeLights Aug 3, 2026
e13e368
test(aud): type pagination ordering fixtures
BeforeLights Aug 3, 2026
0c86fdc
test(prisma): inventory BUA project scope migration
BeforeLights Aug 3, 2026
703cc1f
style(aud): format pagination fixture types
BeforeLights Aug 3, 2026
ad62f45
fix(local): make first-run stack startup reliable
BeforeLights Aug 3, 2026
0617995
fix(local): preserve Linux bootstrap line endings
BeforeLights Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*.kt text eol=lf
*.kts text eol=lf
*.py text eol=lf
*.sh text eol=lf
*.ps1 text eol=crlf
*.bat text eol=crlf
*.cmd text eol=crlf
Expand Down
4 changes: 3 additions & 1 deletion apps/web/test/error-privacy-query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ describe('safe localized recovery', () => {
const router = createAppRouter({ initialEntries: ['/vi-VN/debug/route-error'] });
render(<ApplicationBoundary router={router} />);

expect(await screen.findByRole('heading', { name: 'Không thể mở khu vực này' })).toBeTruthy();
expect(
await screen.findByRole('heading', { name: 'Không thể mở khu vực này' }, { timeout: 5_000 }),
).toBeTruthy();
expect(screen.queryByText(/internal tenant detail/u)).toBeNull();
consoleError.mockRestore();
});
Expand Down
51 changes: 51 additions & 0 deletions docs/operations/coderabbit-pr-29-disposition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# CodeRabbit PR 29 Disposition

Date: 2026-08-03
Promotion PR: [#29](https://github.com/DatabreezeService/databreeze-platform/pull/29)
Automatic review run: `f61cec20-123e-4694-9265-e71aa976b01b`
Reviewed range: `3ed3d77d..86f25c85`

CodeRabbit ran once automatically on the promotion PR. No manual rerun was requested. Every inline, outside-diff, and review-body finding was reproduced against the later `dev` state. Valid gaps were fixed on `fix/coderabbit-promotion-29`; findings already addressed by later `dev` commits are recorded rather than duplicated.

| ID | Finding | Disposition | Evidence |
|---|---|---|---|
| I-01 | Reservation settlement lacked a revision predicate. | Accepted; already fixed on later `dev`. | `216f4a1`, Prisma reservation race test. |
| I-02 | Membership updates could lose a concurrent write. | Accepted; already fixed on later `dev`. | `237ba56`, Prisma membership race test. |
| I-03 | Bootstrap immutability used `JSON.stringify`. | Accepted; already fixed on later `dev`. | `e6800db`, owned-field comparison tests. |
| I-04 | Sign-out did not prove session ownership. | Accepted; already fixed on later `dev`. | `295b911`, cross-user sign-out rejection test. |
| O-01 | API composition did not expose audit and entitlement database options. | Accepted; already fixed on later `dev`. | `4d3f40d`, foundation composition test. |
| M-01 | BUA dropped project scope from usage rows. | Accepted and fixed. Project IDs are persisted, indexed, reconstructed, and included in inherited reads. | `ccbb9d3`, project usage round-trip test, migration `20260803020000_bua_project_usage_scope`. |
| M-02 | Public audit reads were unbounded. | Accepted and fixed. Public event/seal reads now use limits of 1–100 and tenant-bound opaque cursors; event pages verify each immutable digest. | `a5ba31b`, `72064d6`, `bbca81c`, cursor/Prisma/HTTP tests. |
| M-03 | Direct BUA usage persistence was not transactional. | Accepted and fixed. | `a8a5a47`, transaction invocation test. |
| M-04 | Audit append loaded the complete scope history. | Accepted; already fixed on later `dev`. | `ebe73cf`, bounded duplicate/latest lookups. |
| M-05 | Audit reads allegedly verified multiple scopes as one chain. | Rejected as a false positive. The reviewed domain implementation already groups events by canonical scope before verifying each chain. | `packages/domain/src/audit/v1.ts`, multi-scope grouping in `verifyAuditChainV1`. |
| M-06 | Cookie-name validation rejected valid token characters. | Accepted and fixed. | `0615d54`, hyphenated/dotted cookie-name test. |
| M-07 | Production CSRF origins were not configured explicitly. | Accepted; already fixed on later `dev`. | `8ea5ec9`, production-origin configuration test. |
| M-08 | `GET /v1/auth/me` lacked bearer security and a regression guard. | Accepted. The endpoint annotation was already fixed; a contract-wide protected-operation guard was added. | `295b911`, `21eb825`, generated OpenAPI. |
| M-09 | Refresh response declared `refreshToken` as write-only. | Accepted and fixed. | `0483b4b`, generated-schema assertion. |
| M-10 | `sessionDatabase` composition did not create request tenant context. | Accepted and fixed with one shared session adapter instance. | `1bf5650`, foundation composition test. |
| M-11 | MFA factor activation required no factor proof. | Accepted and fixed with a fail-closed proof-verifier port. | `66a9a56`, invalid/valid proof tests. |
| M-12 | IAM membership reads loaded memberships outside the organization. | Accepted; already fixed on later `dev`. | `b7ee10a`, scoped query tests. |
| M-13 | Entitlement endpoints broke the Problem Details convention. | Accepted; already fixed on later `dev`. | `2328dd4`, HTTP problem tests. |
| M-14 | Unsafe-principal test used a malformed bearer token and asserted the wrong path. | Accepted; already fixed on later `dev`. | `44c1fae`, valid-token unsafe-principal test. |
| M-15 | Session authority outages were reported as credential rejection. | Accepted; already fixed on later `dev`. | `7c94a11`, `a62e515`, availability-boundary tests. |
| M-16 | Mutation requests fabricated idempotency keys from request IDs. | Accepted and fixed. Unsafe methods now require an explicit `Idempotency-Key`; read-only methods may use the request ID. | `85d60cc`, adapter and HTTP sign-out tests. |
| M-17 | One malformed membership row could block unrelated reads. | Accepted and fixed. Read paths skip invalid rows while mutation paths remain strict. | `259c92a`, malformed-row isolation test. |
| M-18 | `mfaRequired` should centrally block protected operations. | Rejected as proposed and retained as planned work. The field currently reports enrolled-factor presence, so blocking when true would lock out MFA-enrolled users. Endpoint risk classification and authenticated step-up assertions remain `partial` under Plan 020/IAM-012 and must be implemented as a dedicated vertical slice. | `PrismaSessionLifecycleAdapter.findPrincipal`, `MfaService.requireStepUp`, requirement traceability status. |
| M-19 | Sign-out lacked caller authorization. | Accepted; duplicate of I-04 and already fixed. | `295b911`. |
| M-20 | IAM transaction callbacks incorrectly required root `$transaction`. | Accepted and fixed with a transaction-scoped client type. | `d83eeb9`, compile-time transaction double and repository tests. |
| M-21 | Personal bootstrap chose unstable first matches and display-name markers. | Accepted and fixed. Selection now finds the unique personal organization and deterministically chooses the earliest active workspace/internal project while preserving renamed display values. | `222910a`, multi-organization and rename tests. |
| M-22 | MFA compare-and-set did not enforce the revision in the update predicate. | Accepted; already fixed on later `dev`. | `e668bd4`, stale-revision tests. |
| M-23 | Direct bootstrap save was not transactional. | Accepted; already fixed on later `dev`. | `868c573`, rollback test. |
| M-24 | Organization membership fallback selected an arbitrary workspace. | Accepted; already fixed on later `dev`. | `26ff403`, deterministic workspace selection test. |
| M-25 | Refresh fell back to the presented token when no active family token existed. | Accepted and fixed. Missing or multiple active tokens fail closed and revoke the family. | `cf47989`, missing-active-token test. |
| M-26 | Refresh ignored the session inactivity deadline. | Accepted and fixed. Session, refresh tokens, and access tokens expire atomically at the deadline. | `a5478ae`, inactivity-boundary test. |
| M-27 | MFA lifecycle timestamps were client-controlled. | Accepted and fixed. Enrollment, verification, and recovery timestamps now come from an injected server clock; forged timestamp fields are rejected. | `774d4d5`, application and HTTP tests. |
| M-28 | Response DTO `refreshToken` was marked write-only. | Accepted; duplicate of M-09. | `0483b4b`. |
| M-29 | Documented and machine-enforced commit-budget minimums disagreed. | Accepted; already fixed on later `dev`. | `2c12a91`, orchestration checker and docs. |

## Release handling

- PR #29 remains a historical promotion slice. Review fixes are applied to `dev` first, following the repository rule that feature/fix PRs target `dev` without CodeRabbit.
- Main is not considered releasable until every ordered promotion slice, including this fix branch, has landed and passed its one automatic CodeRabbit review.
- The rejected M-18 proposal does not mark IAM-012 complete; the traceability record remains `partial` until the planned step-up authorization slice is implemented and verified.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Identity, audit, and entitlement reconciliation — 2026-08-03

## Scope

This evidence record covers the 30-commit `feat/foundation-identity-reconciliation` batch based on `dev`. The batch hardens existing IAM, AUD, and BUA foundations; it does not claim completion of Plan 020 or any production release gate.

## Implemented in this batch

- IAM persistence now compares only owned immutable fields, scopes membership and Device lookups before row materialization, applies optimistic revisions to MFA state, binds sessions to the exact sign-in organization/workspace, expires access credentials, separates rejected credentials from authority outages, authorizes sign-out ownership, and bounds cookie/CSRF parsing.
- Membership authority flows only from a containing tenant scope, and the narrowest applicable membership wins. A project or workspace membership cannot authorize its parent or a sibling.
- AUD append paths use scoped, bounded replay/latest lookups; immutable comparisons ignore persistence metadata; read outages return safe retryable `AUDIT_UNAVAILABLE` problems.
- BUA tenant-owned identity lookups and usage reads are scope-bound; immutable comparisons ignore persistence metadata; reservations allow only one terminal transition; API failures return stable Problem Details.

## Conservative requirement state

The traceability manifest marks only requirements with concrete implementation and tests as `partial`. All remain `not-verified`; no P0/P1 release status is promoted. Requirements whose primary behavior is absent—such as invitations, service accounts, account recovery, audit exports/legal holds, commercial billing reconciliation, and usage exports—remain `planned`.

## Evidence

- Domain tests: `packages/domain/test/identity-v1.test.mjs`, `packages/domain/test/audit-v1.test.mjs`, `packages/domain/test/entitlements-v1.test.mjs`, and tenant/authorization/CSRF/MFA suites.
- API tests: `services/api/test/features/iam/`, `services/api/test/features/aud/`, `services/api/test/features/bua/`, `services/api/test/platform/http/`, and `services/api/test/http-contract.test.ts`.
- Persistence: `services/api/prisma/schema/iam.prisma`, `services/api/prisma/schema/aud.prisma`, `services/api/prisma/schema/bua.prisma`, and the ordered IAM session-scope migration.
- Focused verification passed throughout the batch, including TypeScript compilation, Prisma schema validation, 122 domain tests, and the affected API suites.

## Remaining gates

- Plan 020 still requires invitations, ownership transfer workflows, service accounts, signed offline authorization issuance, full permission enforcement, audit action-definition governance, signed independent seals, legal holds/retention/export/restore, provider-independent subscriptions, offline entitlement issuance, reconciliation/exports, client administration surfaces, and real PostgreSQL/backup/security evidence.
- FND-003 remains blocked only on live Docker daemon evidence; this batch does not change its status.
- The feature PR targets `dev` without CodeRabbit. CodeRabbit remains reserved for the later `dev` to `main` promotion PR and is invoked once there.
2 changes: 1 addition & 1 deletion docs/plans/000-platform-program.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Child plans are written and approved before their product slice begins. Each nam

docs/plans/requirement-traceability.json records all 611 IDs with requested trace fields, one primary plan/task, release status, and verified paths only after evidence exists.

`docs/plans/004-luna-max-execution-plan.md` packages the unfinished orchestration tasks into 15 dependency-safe delivery batches. Normal batches contain 30–99 atomic commits, target about 70, keep promotion diffs at or below 260 changed files, and use the `feat/*` or `fix/*` → `dev` → reviewed `main` flow below.
`docs/plans/004-luna-max-execution-plan.md` packages the unfinished orchestration tasks into 15 dependency-safe delivery batches. A normal PR slice contains 30–50 atomic commits; an exceptional completed-task boundary may extend to 79 but never to CodeRabbit's 100-commit limit. Promotion diffs stay at or below 260 changed files and use the `feat/*` or `fix/*` → `dev` → reviewed `main` flow below.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Branch, commit, and review policy

Expand Down
2 changes: 1 addition & 1 deletion docs/plans/003-luna-handoff-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ For each `#### TASK-ID —` item in `002-complete-execution-orchestration.md`:

10. Inspect generated/runtime debris before commit. Do not commit `.venv`, `node_modules`, Gradle state, build output, logs, caches, secrets, local databases, Terraform state, or test reports unless the repository explicitly tracks a sanitized fixture.
11. Commit one independently reversible outcome with a semantic message. Do not combine contracts, an unrelated fix, and a different feature just to increase commit count.
12. Recount the active batch against its base. Do not open a normal PR below 30 commits; target about 70, stop accepting new tasks at 90, and never exceed 99. Split before the promotion diff reaches 280 changed files; the packet target is 260.
12. Recount the active PR slice against its base. Do not open below 30 commits; target 30–50, stop accepting new tasks at 50, and split at the next completed-task boundary. An exceptional boundary must never exceed 79 commits, preserving margin below CodeRabbit's 100-commit limit. Split before the promotion diff reaches 280 changed files; the packet target is 260.

@coderabbitai coderabbitai Bot Aug 3, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n \
  -e '30–70' \
  -e 'hard maximum is 99' \
  -e 'hard cap 99' \
  -e 'preferredMaximum' \
  -e 'hardMaximum' \
  docs/plans tools/repo-cli

Repository: DatabreezeService/databreeze-platform

Length of output: 1672


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- runbook policy references ---'
sed -n '86,104p;168,184p' docs/plans/003-luna-handoff-runbook.md

printf '%s\n' '--- orchestration policy and validator ---'
sed -n '34,50p' docs/plans/execution-orchestration.json
sed -n '1,90p' tools/repo-cli/src/check-execution-orchestration.mjs

printf '%s\n' '--- related plan scope ---'
sed -n '44,60p' docs/plans/000-platform-program.md

printf '%s\n' '--- test expectations ---'
sed -n '132,154p' tools/repo-cli/test/execution-orchestration.test.mjs

Repository: DatabreezeService/databreeze-platform

Length of output: 11911


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import json
import re

runbook = Path("docs/plans/003-luna-handoff-runbook.md").read_text()
policy = json.loads(Path("docs/plans/execution-orchestration.json").read_text())
validator = Path("tools/repo-cli/src/check-execution-orchestration.mjs").read_text()

print("runbook_commit_policy_occurrences:")
for number, line in enumerate(runbook.splitlines(), 1):
    if re.search(r'30[–-](?:50|70)|(?:hard maximum|hard cap)\s+(?:is\s+)?(?:79|99)', line):
        print(f"{number}: {line}")

print("json_commit_budget:", policy.get("commitBudget"))
print("validator_commit_budget_literals:")
for number, line in enumerate(validator.splitlines(), 1):
    if re.search(r'commitBudget|preferredMinimum|preferredMaximum|hardMaximum|79|99', line):
        print(f"{number}: {line}")
PY

Repository: DatabreezeService/databreeze-platform

Length of output: 1620


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- ledger review policy and batch budgets ---'
rg -n -C 8 \
  -e '"reviewPolicy"' \
  -e '"commitBudget"' \
  -e '"preferredMinimum"' \
  -e '"preferredMaximum"' \
  -e '"hardMaximum"' \
  docs/plans/execution-orchestration.json

printf '%s\n' '--- validator budget logic ---'
sed -n '130,180p' tools/repo-cli/src/check-execution-orchestration.mjs
sed -n '180,235p' tools/repo-cli/src/check-execution-orchestration.mjs

printf '%s\n' '--- runbook and plan headings around policy scopes ---'
rg -n '^## |^### |feature PR|promotion PR|delivery.batch|commit budget|commitBudget|30–50|30–70|79|99' \
  docs/plans/003-luna-handoff-runbook.md \
  docs/plans/004-luna-max-execution-plan.md \
  docs/plans/000-platform-program.md

Repository: DatabreezeService/databreeze-platform

Length of output: 25773


Align the runbook commit budgets.

The runbook uses 30–50 commits with a 79-commit maximum for active slices, but lines 99 and 178 use 30–70 with a 99-commit maximum. The ledger and checker enforce a 79-commit batch maximum. Define separate scopes or update the stale references.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/plans/003-luna-handoff-runbook.md` at line 94, Align the commit-budget
references throughout the runbook, especially the stale 30–70 and 99-commit
limits around the ledger and checker guidance, with the enforced 30–50 target
and 79-commit maximum stated in step 12. If those references intentionally
describe a different scope, explicitly label and define that scope; otherwise
update them to the active-slice limits.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System.Collections.Hashtable.Body

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BeforeLights, I cannot determine the intended request from System.Collections.Hashtable.Body.

Please send the message or command that you intended to provide.

You are interacting with an AI system.

13. Push after each stable task boundary. Update the ledger/checkpoint only with verified facts and leave a handoff record if stopping.

## Pull-request and CodeRabbit protocol
Expand Down
Loading
Loading