Skip to content

[comp] Production Deploy#3479

Merged
tofikwest merged 9 commits into
releasefrom
main
Jul 22, 2026
Merged

[comp] Production Deploy#3479
tofikwest merged 9 commits into
releasefrom
main

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.


Summary by cubic

Adds the ISMS Management Review document with end-to-end API, UI, export, and locking, plus deploy-review fixes for narrative seeding, attendee handling, chair clearing, stable ordering, and locked-state UI. Also adds offset pagination for audit logs with caps and total counts in admin and vendor views, and ensures Employee Compliance roles automatically get portal:read/update with hardened role update validation and concurrency (Linear CS-472; feature per CS-726).

  • New Features

    • management_review (9.3): DB models and template seed in packages/db; registers/services for reviews, inputs, and actions in apps/api with narrative seed-if-empty, export sections/extras (owner names), submit gate, locking, deterministic ordering, carried-forward open actions; new page in apps/app with Procedure, meeting details/attendees, Inputs (9.3.2), Outputs (9.3.3), actions, chair sign-off; tests.
    • Audit logs: offset pagination for /v1/audit-logs and admin org endpoint with offset param and { data, total } response; stable sorting and raised take cap (shared admin endpoint max 200); useOffsetAuditLogs core, useAdminAuditLogs and usePaginatedAuditLogs, RecentAuditLogs server pager, admin org and vendor activity wired to load older history; OpenAPI updated; tests.
  • Bug Fixes

    • Heal empty Programme (9.2) / Procedure (9.3) on existing docs; exact client/server attendee parse mirror with member dedupe and trimmed names; “No chair yet” option; outputs editor closes on sign or loss of edit rights; neutral action-owner display when roster is unavailable; deterministic register ordering; cap audit-log offset at 100k and report total capped to the reachable window; robust load-more that doesn’t skip batches; tests.
    • Roles: prevent revoking independently granted portal access when disabling compliance; validate obligations via nested DTO and use exact boolean checks; validate only newly granted permissions; guard updates with optimistic concurrency (409); build update response from validated data; controller documents 409; tests.
    • Comments: show the actual error reason when a delete fails.

Written for commit 25ac1d9. Summary will update on new commits.

Review in cubic

* fix(app): grant portal permission automatically when Employee Compliance is enabled

* fix(app): update test name in PermissionMatrix

* fix(app): assert onObligationsChange isn't called on unrelated permission changes

* fix(api): enforce compliance-obligation-implies-portal invariant server-side

* fix(api): enforce compliance-obligation-implies-portal invariant server-side

---------

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: chasprowebdev <70908289+chasprowebdev@users.noreply.github.com>
Co-authored-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app (staging) Ready Ready Preview, Comment Jul 22, 2026 8:16pm
comp-framework-editor (staging) Ready Ready Preview, Comment Jul 22, 2026 8:16pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
portal (staging) Skipped Skipped Jul 22, 2026 8:16pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/app/src/app/(app)/[orgId]/settings/roles/components/PermissionMatrix.tsx Outdated
Comment thread apps/api/src/roles/roles.service.ts Outdated
Comment thread apps/api/src/roles/roles.service.ts
salcompai and others added 2 commits July 22, 2026 12:38
Signed-off-by: salcompai <sal@trycomp.ai>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ tofikwest
❌ salcompai
You have signed the CLA already but the status is still pending? Let us recheck it.

* feat(api): add isms management review (clause 9.3) document type

Tenth ISMS document type management_review, cloned from the internal
audit (9.2) and monitoring (9.1) patterns:

- IsmsManagementReview / IsmsReviewInput / IsmsReviewAction models with
  server-generated MR-YYYY-NN and A-NN references under the per-document
  lock, an immutable recordedAt, and attendees frozen at selection
- ten Inputs (9.3.2) rows seeded per review at creation, idempotent by
  inputKey; outputs ship with clause-9.3 template text
- chair and attendees default to the Roles (5.3) Top Management and SPO
  holders, deduped for small teams
- chair sign-off locks the review (inputs and outputs frozen, sign-off
  slot correctable); action tracking stays live to closure and open
  actions carry forward to the next review's input (a) at display and
  export time, never copied
- submit gate assertManagementReviewComplete mirrors the ticket's
  document validation for complete reviews; agenda-pack reviews never
  block
- reviews/review-inputs/review-actions registers on the generic
  dispatch, export section builder, narrative (procedure) seeding, and
  extras threading at both snapshot call sites

* feat(app): management review (clause 9.3) page

ISMS > Management Review detail page for the tenth document type:

- ManagementReviewClient shell with the clause-9.3 submit-gate mirror
  (management-review-constants.ts) and the editable Procedure card
- review cards with meeting date (backdatable), immutable recorded-on,
  chair dropdown from the Roles (5.3) Top Management holder, attendees
  as a select-to-add list frozen at selection, and the bracketed
  suitable/adequate/effective conclusion verdict
- Inputs (9.3.2) table as the meeting agenda: per-row edit, immediate
  Discussed? checkbox, add/remove rows
- Outputs (9.3.3): decisions + changes template text and the actions
  arising table with immediate status tracking and full MR-YYYY-NN-ANN
  references
- open actions from earlier reviews render as a read-only carried-
  forward table on later reviews
- single chair sign-off slot that locks the review in the UI exactly as
  the server enforces it (action tracking and the sign-off slot itself
  stay live)
- vitest coverage incl. admin vs read-only permissions and the locked
  state; existing ISMS fixtures gained the new reviews register

* fix(isms): harden management review sign-off lock and attendee handling

Review-round fixes:

- re-read the sign-off state INSIDE the locked transaction for every
  mutation gated on "unsigned" (review update/delete, input CRUD, action
  create/delete) — a concurrent chair sign-off could previously commit
  between the pre-read and the lock and be overwritten
- signed reviews now accept only owner / due date / status on their
  actions; the description is part of the frozen minutes
- action rows patch only dirty fields, so an untouched owner belonging
  to a former member no longer fails unrelated edits
- review details and input rows exit edit mode when the lock lands
- attendee picker resets to its placeholder after each selection and
  saves are serialized so replacement PATCHes cannot drop each other
- attendee lists are deduped by member before persisting
- client attendee parsing requires a non-empty memberId, mirroring the
  server schema
- edited seeded input rows record source=manual (audit-controls
  precedent)

---------

Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
Co-authored-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 72 files

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread apps/app/src/app/(app)/[orgId]/documents/isms/components/ReviewOutputsSection.tsx Outdated
Comment thread apps/api/src/isms/documents/management-review-defaults.ts
Comment thread apps/api/src/isms/documents/management-review-defaults.ts Outdated
* fix(isms): management review deploy-review fixes

Post-merge review round on the production deploy PR:

- ensure-setup now heals an empty Programme (9.2) / Procedure (9.3)
  paragraph on EXISTING documents, not only ones created in the same
  call — a document left blank (e.g. a crash between provision and
  seed) previously stayed blank forever; the per-doc updateMany guard
  still protects populated drafts
- attendee parsing is now an exact client/server mirror: all-or-nothing
  on malformed entries and deduped by member on read, so the Submit UI
  and the server gate always agree and duplicate legacy entries cannot
  render duplicate chips or duplicate keys
- the chair select gained an explicit "No chair yet" option so a stale
  chair can be cleared, not only replaced
- the outputs editor closes when the review becomes signed or edit
  rights are lost, matching the other locked-state affordances
- action-owner display stays neutral ("Unknown member") when the people
  roster is unavailable instead of mislabeling active owners as former
  members
- deterministic ordering tie-breakers on review lists (position,
  createdAt, id) and role assignments (position, id) so carry-forward
  attribution and participant defaults are reproducible when positions
  collide
- seeded inputs (c) and (d.4) point at the canonical ISMS document
  titles so the agenda references are followable

* fix(isms): trim attendee names in the client parse mirror

The server zod schema trims names on parse, so a legacy " Jane " entry
rendered with spaces in the UI but trimmed in the generated minutes.
The client parse now trims too, keeping both representations identical.

---------

Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
* feat(admin): paginate org audit log activity beyond the first 100

The platform-admin "Recent Activity" panel hard-capped at 100 records with
no way to see older history. Add offset pagination end-to-end:

- API: `getAuditLogs` accepts `offset`, returns `{ data, total }` (parallel
  count), raises the `take` ceiling to 200, and adds a stable `id` secondary
  sort so offset paging is deterministic across batches.
- App: `useAdminAuditLogs` accumulates 100-row batches by offset and derives
  `hasMore` from the server total.
- `RecentAuditLogs` gains optional server-pagination props: the › arrow stays
  enabled until the genuine last page (ceil(total / pageSize)) and the next
  batch is fetched automatically when paging past the loaded window — so the
  arrow is only enabled when there's actually more to load.

Adds RecentAuditLogs pager tests (smart next-arrow from server total,
load-more at the batch boundary, legacy backward-compat) and extends the
admin-organizations service spec for offset/take/total.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(vendors): paginate vendor activity so older assignee changes stay visible

The vendor detail "Recent Activity" panel fetched /v1/audit-logs with no
offset and no total, so it only ever showed the newest 50 combined vendor +
task-item events. On a busy vendor, older `vendor` events (e.g. an assignee
change) fell off with no way to page to them — they were logged, just
unreachable in the UI.

- API: `/v1/audit-logs` now accepts `offset`, returns `{ data, total }`
  (parallel count), and adds a stable `id` secondary sort so offset paging is
  deterministic. `take` semantics unchanged (default 50, max 100). Purely
  additive — the existing non-paginated `useAuditLogs` consumers are unaffected.
- App: extract the offset-accumulate machinery into a shared
  `useOffsetAuditLogs` core (used by the admin pager too, now a thin wrapper)
  and add `usePaginatedAuditLogs` for entity-scoped views. The core resets its
  window when the filter identity changes (e.g. a vendor's task-item ids load).
- Vendor activity section wires the paginated hook into RecentAuditLogs' server
  pager (load-more + smart next arrow).

Tests: audit-log controller spec covers offset/total/count; useOffsetAuditLogs
spec covers accumulate/dedupe/hasMore/filter-reset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(audit): address cubic review on audit-log pagination

- P1: offset pager no longer skips a batch on a failed load-more. `loadMore`
  only advances once the current batch has settled successfully; while it's
  loading or errored (SWR retries the same offset) it's a no-op, so no rows are
  dropped from the pager. Covered by a new hook test.
- Cap `offset` on both audit-log endpoints (shared /v1/audit-logs and the admin
  org endpoint) at MAX_AUDIT_LOG_OFFSET (100k) so an unbounded ?offset= can't
  force arbitrarily large table scans. Constant lives in a dependency-free
  module so it doesn't drag Prisma enums into unit-test module graphs.
- Add the missing admin-controller test for the offset param and cap tests for
  both endpoints.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(docs): regenerate openapi with audit-logs offset param

Picks up the new `offset` query param on GET /v1/audit-logs so the generated
MCP `get-audit-logs` client can page past the first batch. Addresses the last
open cubic finding on #3480.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(audit): cap reported total at the reachable offset window

Follow-up to the offset cap: the endpoints returned the true row count while
clamping any offset past MAX_AUDIT_LOG_OFFSET to the same page. Past the cap the
client's `hasMore = logs.length < total` stayed true, so the pager looped
load-more over pages that could never be filled.

Report `min(count, MAX_AUDIT_LOG_OFFSET)` from both audit-log endpoints so
`hasMore` and the pager's page count stop at the accessible boundary. No client
change needed. Covered by cap-total tests on both specs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…y PR (#3483)

* fix(api): stop revoking independently-granted portal access when disabling compliance

* fix(api): use exact boolean check for compliance obligation, validate via DTO

* fix(api): validate only newly-granted permissions on role update, not the full set

* fix(api): guard role updates with optimistic concurrency on updatedAt

* fix(api): build update response from validated data, not a second DB read

* fix(api): document 409 conflict response on role update endpoint

---------

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: chasprowebdev <70908289+chasprowebdev@users.noreply.github.com>
…3485)

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>
@vercel
vercel Bot temporarily deployed to staging – portal July 22, 2026 20:13 Inactive
@tofikwest
tofikwest merged commit 984a86a into release Jul 22, 2026
13 of 14 checks passed
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.107.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants