Route audit-log and SCIM-event exports through export_jobs with typed
arguments, an iam BuildAndUploadExport/SendExportEmail implementation,
and a concurrent export-job worker with stale recovery. Stream JSONL via
page.WalkAll into S3, and expose the request flow on console, connect,
MCP, and CLI.
Co-authored-by: Bryan Frimin <bryan@getprobo.com>
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
Introduce device, posture, and enrollment-token entities with ITAM
service policies for agent-managed fleet inventory.
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
Unbounded LoadAll* loaders materialised an entire result set in one
query with no ceiling. A table that is small in development can grow
without bound in production, so these loaders were a latent memory
and query-time hazard.
Remove the LoadAll* methods from pkg/coredata and walk the cursor-
paginated LoadBy* siblings instead through a shared page.LoadAll
helper. The helper advances a MaxCursorSize forward cursor until the
result set is exhausted and concatenates the pages. It caps a single
call at MaxLoadAllPages (20) batches of 500 rows and errors past that
rather than materialising an unbounded set, so a runaway caller fails
loudly instead of exhausting memory.
Callers that genuinely need every row now express that explicitly,
and the coredata load-naming rule and docs are updated to discourage
new unbounded loaders.
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
Remove dead 23505 checks on single-GID primary keys (oauth2_consent,
risk_assessment, risk_assessment_scenario, risk_assessment_scope).
Add missing constraints to membership_profile and
statement_of_applicability. Document composite-PK vs GID-PK rule in
cursor rules and contrib guide.
Signed-off-by: Émile Ré <emile@probo.com>
Replace the cross-entity JOIN in
DetectedTrackers.LoadCommonThirdPartyIDByDomainMatch with two
idiomatic coredata calls: LoadInitiatorDomainsByTrackerPatternID
on DetectedTrackers, then a new CommonThirdPartyDomains.Load with
a CommonThirdPartyDomainFilter. Each entity now queries only its
own table, and the caller orchestrates the lookup.
Document the Load vs LoadAll naming convention and the no
cross-entity JOINs rule in contrib/claude/coredata.md.
Signed-off-by: Émile Ré <emile@probo.com>
Upsert methods now RETURNING all struct columns and scan the result
back into the pointer receiver, keeping the caller in sync with the
actual DB state (id, created_at, etc. from the existing row on
conflict). Insert detection compares the saved original ID with the
returned ID instead of relying on the PostgreSQL-internal xmax column.
Signed-off-by: Émile Ré <emile@probo.com>
Checking only pgErr.Code == "23505" is insufficient when a
table has multiple unique constraints. Always verify
pgErr.ConstraintName as well to avoid mapping unrelated
violations to the wrong sentinel error.
Signed-off-by: Émile Ré <emile@probo.com>
The register/document model has fully replaced the snapshot system.
Delete every snapshot-scoped row and strip the application code that
referenced them: SnapshotID/SourceID struct fields, snapshot_id IS NULL
filters, snapshot columns from SELECT/INSERT statements and named args,
and the eight migrate-*-snapshots-to-documents one-shot tools.
The remaining snapshot_id / source_id columns, the snapshots and
controls_snapshots tables, the snapshots_type enum, and the
snapshot-scoped indexes are now unused; they are dropped in a follow-up
schema migration so this change can roll back cleanly without leaving
orphaned data.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Remove assets from the snapshot system and replace with a publish-based
document workflow that generates versioned ProseMirror documents.
- Remove snapshot_id/source_id from asset and asset_vendor models
- Delete AssetFilter (no longer needed without snapshot filtering)
- Add PublishAssetList service, GraphQL mutation, MCP tool, CLI command,
and n8n operation
- Add asset_list_document_id column to generated_documents table
- Generate ProseMirror documents with asset inventory tables
(name, type, amount, data types stored, owner, vendors)
- Add AssetListDocument resolver on Organization type
- Update frontend to remove snapshot routes/params and add publish dialog
- Add e2e tests for asset publish (immediate, with approvers, reuse, RBAC)
- Add migration script for converting legacy asset snapshots to documents
- Exclude ASSETS from snapshot type lists and e2e snapshot tests
- Move generated_documents SQL to coredata methods on Datum and Asset
- Clear generated document and SOA references on soft delete and archive
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Address PR review comments: capture Exec result and check
RowsAffected() == 0 to return ErrResourceNotFound in
Cookie.Update, CookieCategory.Update, and CookieCategory.UpdateRank.
Also update coredata and relay contributor docs accordingly.
Signed-off-by: Émile Ré <emile@getprobo.com>
Add coredata guide section on using Go enum constants as named
SQL parameters instead of hardcoded string literals. Fix mixed
inline/multiline RenderJSON call in cookie banner handler.
Signed-off-by: Émile Ré <emile@getprobo.com>
Add organization_id to cookie_banner_versions, cookie_categories,
and cookie_consent_records so AuthorizationAttributes can return
it directly without JOINing back to cookie_banners. Document the
pattern in contrib/claude/coredata.md.
Signed-off-by: Émile Ré <emile@getprobo.com>
Clarify that indexes should not be added speculatively and
should only be introduced when justified by production query
latency. Also document that columns should avoid DEFAULT
clauses, with guidance on backfilling non-nullable columns.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Replace three instances of leftover %T format verbs in logger.ErrorCtx() calls with proper structured logging fields. Add alphabetically-sorted reference documentation for six new contrib/claude/ guides and reorder the existing list.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>