# 0025 — Security — Module Triage

**Milestone:** M3
**Owner:** TBD
**Status:** planning

## Goal

Consolidates 49 legacy issues from the
`MetaDrivenPlatform4AI` repo that share the same module / area label,
so they can be triaged together by the corresponding domain IC.

Module label scope: `module/security`.

## Acceptance criteria

- [ ] All `ported` children below have a Story or Bug filed in pingcap-pack
- [ ] All filed Stories / Bugs have a linked test (existing or to-write task with scaffold)
- [ ] Engineering review confirms which children are still applicable under the new project's design

## Stories / Bugs (filed as GitHub issues)

49 children classified `ported`. Phase 3/4 will file each as
a Story (capability) or Bug (defect) in this repo and back-reference the
legacy issue. Initial child list:

- [ ] #TBD — legacy MetaDrivenPlatform4AI#44 — [P1][Security] Potential permission bypass in lookup hydration exposes referenced record names
- [ ] #TBD — legacy MetaDrivenPlatform4AI#92 — Folder share API request/response schema differs from Salesforce
- [ ] #TBD — legacy MetaDrivenPlatform4AI#153 — Query/search return records without record-level access enforcement (sharing/RLS...
- [ ] #TBD — legacy MetaDrivenPlatform4AI#154 — SOSL/parameterized search return fields without FLS checks (`backend/internal/fe...
- [ ] #TBD — legacy MetaDrivenPlatform4AI#163 — `/debug/pprof` exposed without authentication/authorization
- [ ] #TBD — legacy MetaDrivenPlatform4AI#170 — Field-level security is not enforced on insert (CreateRecord/Upsert create path)
- [ ] #TBD — legacy MetaDrivenPlatform4AI#179 — Row-Level Security (RLS) is not enforced for Query/Search (data exfiltration)
- [ ] #TBD — legacy MetaDrivenPlatform4AI#185 — External-ID upsert leaks existence via permission-bypassing read (`repo.FindOneByField`)
- [ ] #TBD — legacy MetaDrivenPlatform4AI#533 — fix: Profile permissions broken — use PermissionSet standard model
- [ ] #TBD — legacy MetaDrivenPlatform4AI#668 — Verify OWD/ViewAllRecords/ControlledByParent enforcement after CheckRecordAccess refactor
- [ ] #TBD — legacy MetaDrivenPlatform4AI#669 — Expose EnableHierarchySharing toggle in Setup UI
- [ ] #TBD — legacy MetaDrivenPlatform4AI#671 — UX: Hide Edit/Delete buttons when user lacks record-level access
- [ ] #TBD — legacy MetaDrivenPlatform4AI#676 — fix: batch record-access endpoint computes access from FLS-filtered records
- [ ] #TBD — legacy MetaDrivenPlatform4AI#748 — Object CRUD permissions not enforced for standard objects
- [ ] #TBD — legacy MetaDrivenPlatform4AI#770 — feat: UserEditorModal — metadata-driven field rendering (User↔Role visibility)
- [ ] #TBD — legacy MetaDrivenPlatform4AI#794 — cleanup: remove legacy _System_ProfilePermission remnants after system-permission SSoT migration
- [ ] #TBD — legacy MetaDrivenPlatform4AI#815 — arch: Missing metadata lifecycle layer — permission cascade not wired to EventBus (root cause of #527; #524; #526)
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1134 — Add singleflight guard to roleHierarchy lazy-refresh to prevent thundering herd
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1135 — Throttle roleHierarchy refresh retries on DB error to avoid retry storm
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1136 — Integration test: SQL-seeded role is visible to manager without backend restart
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1253 — Harden bcrypt detection heuristic in password hashing
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1256 — Enforce minimum bcrypt cost factor on pre-computed password hashes
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1257 — Verify authorization gate on _System_User password field writes
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1266 — CSRF token generation silently returns empty string on rand.Read failure
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1279 — Externalize hardcoded test Connected App credentials from source code
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1280 — Hard-fail admin password resolution in production when NEXUS_ADMIN_PASSWORD is unset
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1315 — ShareRecordModal entity search missing IsActive filter on Group query
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1346 — Remove or document redundant profile→PermissionSet resolution in getObjectPermissions/getFieldPermissions
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1406 — Frontend should use /permissions/effective endpoint for user-specific button visibility
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1411 — bug: PermissionSet API creation requires ProfileId for standalone (non-profile-owned) Permission Sets
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1413 — E2E test tracking: User/Permission 50-case test suite — 40 PASS; 4 blocked; 6 skipped
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1461 — [P2] FLS on write: field-level deny returns HTTP 400 instead of silent strip — entire PATCH rejected
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1462 — [UX Gap] Role Hierarchy tree: no way to see which users belong to a role — only aggregate user-count badge
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1475 — ObjectPermissions: setting PermissionsModifyAllRecords=true does not cascade to Delete or ViewAllRecords
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1477 — Owner-based SharingRule cannot be created via API — schema requires Criteria; but validator forbids Criteria+SharedFromRoleId together
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1478 — Nested groups not supported — GroupMember.UserOrGroupId FK constrained to User only
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1480 — [Phase A] Setup → Security: metadata-driven page shell
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1481 — [Phase B] Setup → Security: consolidate ProfilesView + migrate hand-rolled portals to BaseModal
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1482 — [Phase C] Setup → Security: typed Badge intents + RowActions + StatusPill primitives
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1582 — Setup → New User modal: 165 form inputs; 17 required fields; Chatter/Lightning preferences dumped into create form
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1599 — [Gate][Backend] Permanent permission gate on Flow/Dashboard/Report create endpoints
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1602 — [Gate][Bootstrap] Prod-only default: Create* authoring permissions = false; dev/staging unaffected
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1764 — User.Name synthesis uses wrong source columns — produces '<email> <email>' instead of '<FirstName> <LastName>'
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1776 — fix(integration/hubspot): cap request body size before HMAC verification to prevent unauthenticated memory DoS
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1778 — observability(integration/hubspot): emit metric on HMAC signature verification failures
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1978 — PR #1937 regression — admin PermissionSet filter helper uses 'IS NULL' which NexusCRM SOQL parser doesn't support; Setup→PS / Assign PS / Connected App PS picker all broken
- [ ] #TBD — legacy MetaDrivenPlatform4AI#1995 — Setup → User → Assign Permission Sets: 'already assigned' section displays shadow PSA rows (cryptic UUID labels; non-removable) — Salesforce-synced data exposed in a UI surface that should hide it
- [ ] #TBD — legacy MetaDrivenPlatform4AI#2289 — Permission Set Groups not exposed in UI despite backend SObjects existing — /setup/permission-set-groups redirects to /
- [ ] #TBD — legacy MetaDrivenPlatform4AI#2290 — PS Edit Permissions panel missing App Permissions; Tab Settings; Record Type Access; and Custom Permissions tabs

## Non-goals

- Re-port legacy fixes that are no longer relevant under the new project's
  pure-platform design — engineering identifies these case-by-case
- Layer-belonging classification (L0 / L1 / L2) — engineering's job

## History

- 2026-05-03 — created during Phase 2 from clustered orphan issues.

## Stories (filed in Phase 3)

_Pending Phase 3 synthesis._
