You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* fix(webhooks): enforce tenant dispatch scope
Carry tenant_id through webhook dispatch jobs and re-check scope in the worker so tenant-scoped webhooks cannot receive another tenant's payload.
Allow worker and embedding backfill commands to use an explicitly configured local DATABASE_URL while still rejecting implicit defaults.
Refs ENG-796
* fix(webhooks): enforce tenant dispatch scope
Carry tenant_id through webhook dispatch jobs and re-check scope in the worker so tenant-scoped webhooks cannot receive another tenant's payload.
Allow worker and embedding backfill commands to use an explicitly configured local DATABASE_URL while still rejecting implicit defaults.
Refs ENG-796
* docs: fix AGENTS markdown spacing
* test(webhooks): keep repository scope test out of unit CI
* chore: restore tests workflow
* fix: tighten webhook tenant isolation
* chore: revert delete api
* chore: allow deleting specific tenant id
* chore: add gdpr exception
* chore: address pr comments
* chore: lint fix
* fix: harden webhook delete payload dispatch
Copy file name to clipboardExpand all lines: AGENTS.md
+13Lines changed: 13 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,6 +25,19 @@
25
25
- Prefer Go naming conventions (CamelCase for exported, lowerCamel for unexported).
26
26
- Keep package names short and domain-focused (e.g., `repository`, `service`).
27
27
28
+
## Multi-Tenancy & Data Isolation
29
+
30
+
- Treat `tenant_id` as a security boundary, not a convenience filter. Tenant-owned data must never be read, enqueued, dispatched, cached, searched, embedded, or deleted across tenants.
31
+
- Exception: GDPR/right-to-erasure flows may intentionally delete all records for a data subject across tenants when that is the documented API contract. Make that all-tenant behavior explicit in the API docs, service/repository names or comments, logs, and tests; do not reuse it for normal tenant-owned workflows.
32
+
- When making a model, migration, API request, or repository change involving tenant-owned data, audit every downstream path that carries or derives from that data: handlers, services, repositories, message publishers, River job args, workers, webhook payloads, search, embeddings, bulk operations, logs, and metrics.
33
+
- Tenant access rules must be consistent across every path that can observe, mutate, derive from, or act on the same resource. If one API endpoint, repository method, search path, webhook dispatch path, worker, backfill, bulk operation, or export path requires tenant scope, every alternate path for that resource must enforce the same tenant boundary.
34
+
- Do not model `tenant_id` as an optional filter for tenant-owned resources. Prefer required tenant parameters in service/repository method signatures (`tenantID string`, not `*string`) unless the domain explicitly supports global resources and documents that behavior.
35
+
- Prefer tenant-aware repository/service methods for tenant-owned workflows. Avoid adding broad helpers that return all enabled/all matching resources when the caller is dispatching, processing, deriving, exporting, or exposing tenant data.
36
+
- Async jobs must carry the tenant boundary when the source data has one, and workers must re-check tenant scope before doing side effects. Do not rely only on enqueue-time filtering.
37
+
- Global resources may intentionally have `tenant_id = NULL` only when the domain explicitly documents them as non-tenant-owned. Webhooks are tenant-owned and must require a non-empty `tenant_id`; a missing tenant on event data must not match any webhook.
38
+
- When changing access rules for a tenant-owned model, search for all alternate access paths by resource name and by derived side effects: list, get, update, delete, bulk delete, webhook fan-out, River jobs, workers, embeddings, search, exports, cache invalidation, logs, and metrics.
39
+
- For any tenant-scoping change, include verification at the boundary where the leak could happen: database query behavior, service fan-out, worker execution, and API behavior when relevant. Include at least one alternate-path regression test proving that data allowed through the primary path cannot leak through async dispatch, bulk operations, derived indexes, exports, or background workers. Tests are the evidence; the invariant belongs in the architecture.
40
+
28
41
## Testing Guidelines
29
42
- Tests live under `tests/` and are run with `go test ./tests/...`.
30
43
- Name test files `*_test.go` and test functions `TestXxx`.
0 commit comments