feat: Add ability to limit visibility of roadmaps and changelogs by segment#269
Open
arcdigital wants to merge 2 commits into
Open
feat: Add ability to limit visibility of roadmaps and changelogs by segment#269arcdigital wants to merge 2 commits into
arcdigital wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces segment-based audience visibility controls for roadmaps and changelog entries, aligning them with the existing tiered access model used elsewhere (e.g., boards). It adds access JSONB fields (with defaults/migrations), policy checks + SQL filters (with parity tests), and wires the new access controls through REST endpoints and the admin UI.
Changes:
- Add
RoadmapAccess/ChangelogAccesstypes + DB columns/migrations, replacing legacyroadmaps.is_public. - Implement policy-layer authorization (
canView*) and list-query SQL predicates (*ViewFilter) with parity tests. - Update REST routes, server functions, and admin UI to read/write
access(keeping roadmapisPublicfor back-compat on REST).
Reviewed changes
Copilot reviewed 50 out of 50 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/db/src/types.ts | Adds RoadmapAccess / ChangelogAccess types and defaults. |
| packages/db/src/seed.ts | Seeds roadmaps using access instead of isPublic. |
| packages/db/src/schema/changelog.ts | Adds changelog_entries.access JSONB column default in schema. |
| packages/db/src/schema/boards.ts | Replaces roadmaps.isPublic with roadmaps.access and drops index. |
| packages/db/src/tests/types.test.ts | Updates Roadmap type expectation from isPublic → access. |
| packages/db/src/tests/schema.test.ts | Updates schema tests for new access column + regression guard. |
| packages/db/drizzle/meta/_journal.json | Registers migrations 0114/0115 in Drizzle journal. |
| packages/db/drizzle/0115_changelog_access.sql | Adds access column to changelog_entries (additive). |
| packages/db/drizzle/0114_roadmap_access.sql | Adds/backfills roadmaps.access, drops is_public + index. |
| apps/web/src/routes/api/v1/roadmaps/index.ts | REST create/list: accept access + derive legacy isPublic. |
| apps/web/src/routes/api/v1/roadmaps/$roadmapId.ts | REST get/update: return access + derive legacy isPublic. |
| apps/web/src/routes/api/v1/changelog/index.ts | REST create/list: accept/return access. |
| apps/web/src/routes/api/v1/changelog/$entryId.ts | REST update: accept access; response includes access. |
| apps/web/src/lib/shared/schemas/roadmaps.ts | Adds shared Zod validation for RoadmapAccess. |
| apps/web/src/lib/shared/schemas/changelog.ts | Adds shared Zod validation for ChangelogAccess. |
| apps/web/src/lib/shared/db-types.ts | Re-exports new access types/defaults for client-safe imports. |
| apps/web/src/lib/server/policy/roadmaps.ts | Adds roadmap visibility policy + SQL filter. |
| apps/web/src/lib/server/policy/index.ts | Exports new roadmap/changelog policies. |
| apps/web/src/lib/server/policy/changelog.ts | Adds changelog visibility policy + SQL filter. |
| apps/web/src/lib/server/policy/tests/roadmaps.test.ts | Adds matrix tests for canViewRoadmap. |
| apps/web/src/lib/server/policy/tests/roadmap-view-filter-parity.test.ts | Adds execution-level parity test for roadmap filter. |
| apps/web/src/lib/server/policy/tests/changelog.test.ts | Adds matrix tests for canViewChangelog. |
| apps/web/src/lib/server/policy/tests/changelog-view-filter-parity.test.ts | Adds execution-level parity test for changelog filter. |
| apps/web/src/lib/server/functions/roadmaps.ts | ServerFns updated to read/write access. |
| apps/web/src/lib/server/functions/public-posts.ts | Public roadmap listing now resolves actor + applies access filter. |
| apps/web/src/lib/server/functions/portal.ts | Portal public roadmaps now resolve actor + return access. |
| apps/web/src/lib/server/functions/embeds.ts | Embed changelog meta lookup now includes actor for access filtering. |
| apps/web/src/lib/server/functions/changelog.ts | Public changelog read/list now resolve actor + apply access. |
| apps/web/src/lib/server/functions/tests/portal-gate-public-posts.test.ts | Updates roadmap fixtures to use access. |
| apps/web/src/lib/server/functions/tests/portal-gate-extended.test.ts | Updates roadmap fixtures to use access. |
| apps/web/src/lib/server/domains/roadmaps/roadmap.types.ts | Updates service input types to accept access. |
| apps/web/src/lib/server/domains/roadmaps/roadmap.service.ts | Persists access, adds isPublic back-compat helpers, updates public list to actor-aware filter. |
| apps/web/src/lib/server/domains/roadmaps/roadmap.query.ts | Public roadmap posts now 404 on denied access (uses canViewRoadmap). |
| apps/web/src/lib/server/domains/roadmaps/tests/roadmap-public-moderation.test.ts | Updates mock roadmap shape to use access. |
| apps/web/src/lib/server/domains/roadmaps/tests/roadmap-public-audience.test.ts | Updates mock roadmap shape to use access. |
| apps/web/src/lib/server/domains/changelog/changelog.types.ts | Adds access to changelog domain types. |
| apps/web/src/lib/server/domains/changelog/changelog.service.ts | Persists access with default, supports updates, returns access. |
| apps/web/src/lib/server/domains/changelog/changelog.query.ts | Includes access in list results. |
| apps/web/src/lib/server/domains/changelog/changelog.public.ts | ANDs audience gate into public changelog visibility conditions. |
| apps/web/src/lib/server/domains/api/schemas/roadmaps.ts | OpenAPI schema now includes access and legacy isPublic semantics. |
| apps/web/src/lib/server/domains/api/schemas/changelog.ts | OpenAPI schema now includes access. |
| apps/web/src/lib/client/mutations/roadmaps.ts | Client mutations updated to send access. |
| apps/web/src/lib/client/hooks/use-roadmaps-query.ts | Roadmap view type updated to expose access. |
| apps/web/src/components/admin/roadmaps/roadmap-access-control.tsx | New admin UI control for selecting roadmap visibility tier + segments. |
| apps/web/src/components/admin/roadmap-sidebar.tsx | Replaces public switch with access control + validation. |
| apps/web/src/components/admin/changelog/create-changelog-dialog.tsx | Adds access state + passes to create mutation; disables submit on invalid segments. |
| apps/web/src/components/admin/changelog/changelog-modal.tsx | Adds access state + passes to update mutation; disables submit on invalid segments. |
| apps/web/src/components/admin/changelog/changelog-metadata-sidebar.tsx | Plumbs access props into metadata sidebar. |
| apps/web/src/components/admin/changelog/changelog-metadata-sidebar-content.tsx | Renders access control in changelog metadata sidebar UI. |
| apps/web/src/components/admin/changelog/changelog-access-control.tsx | New admin UI control for changelog audience tier + segments. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
69a1634 to
8fb0083
Compare
8fb0083 to
adec079
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add audience visibility controls to roadmaps and changelogs
Summary
This MR brings roadmaps and changelogs onto the same tier-based access model
already used by boards, so an admin can scope a roadmap or changelog entry to
anonymous (public), authenticated users, specific segments, or
team-only.
Access model
Both reuse the shared
AccessTier(anonymous | authenticated | segments | team)so the policy layer stays uniform. Unlike
BoardAccess(view/vote/comment/submit),roadmaps and changelogs have only a
viewaction, so each gets a minimal shape:Key behaviors:
segmentstier with an empty allowlist hidesthe item and is rejected on save — it never silently falls open to public.
restricted tier can't be used to probe which items exist.
canViewX()single-row check is paired with axViewFilter()SQL predicate for list queries, and a parity test asserts thetwo agree row-by-row — so a list and a direct fetch can never disagree about
visibility.
publishedAtstill decides whether/when an entry is live;
accessdecides who may seea live entry. The audience gate is AND-ed into the existing public-visibility
conditions shared by all public read paths.
API compatibility
The REST API keeps the legacy
isPublicboolean for backward compatibility:isPublicis derived (access.view === 'anonymous') and thefull
accessobject is also returned.accesstakes precedence; when onlyisPublicis supplied itis mapped onto an access object (
true → anonymous,false → team).Migrations
0114_roadmap_access— breaking column swap. Adds theaccessjsonb,backfills from
is_public(true → anonymous,false → team), drops theroadmaps_is_public_idxindex, then drops theis_publiccolumn. Thebackfill is mandatory: without it, previously-private roadmaps would inherit
the
anonymousdefault and become public.0115_changelog_access— purely additive. Adds theaccessjsonb withan
anonymousdefault, so every existing entry stays public. No backfillneeded.
What changed
Data / types
packages/db—RoadmapAccess/ChangelogAccesstypes + defaults, schemacolumns, migrations
0114/0115, seed + schema/type tests.Policy
policy/roadmaps.tsandpolicy/changelog.ts(single-row check + listfilter), exported from
policy/index.ts.*-view-filter-parity.test.ts) plus dedicated policy tests.Server / API
caller's actor and apply the view filter.
/api/v1/roadmaps,/api/v1/changelog) and internal serverfunctions accept
access(withisPublicback-compat) and return both.Admin UI
RoadmapAccessControlandChangelogAccessControlcomponents (tierpicker + segment allowlist), wired into the roadmap sidebar and the changelog
create dialog / metadata sidebar / modal. Save is disabled while a
segmentsselection has an empty allowlist.
Testing notes
surfaces; existing roadmap/portal-gate tests were updated from
isPublictoaccess.db:migrateagainst a copy first —0114dropsroadmaps.is_public.Verify any external readers of that column are updated.
to that segment, and confirm a non-member (anonymous and authenticated) gets a
404 / omission while a member sees it.
Implements #262 and #271