Initial curated RAGcore source from c16667f0c9397e2bfc8dd0255b114fba23c8d05e

This commit is contained in:
Public Source Publisher committed 2026-10-01 01:34:21 +02:00
commit 7ca726caf2
659 files changed
+98171

No files matched your search

+94
View File
@@ -0,0 +1,94 @@
# Security Controls
## Identity
OIDC voor mensen; gehashte, roteerbare service tokens met scopes en expiry voor applications. Tokens worden slechts eenmaal getoond.
## Authorization
Deny by default, explicit grants, effective-space intersection, use-case policies, database scoping, verplichte Qdrantfilters en resource reauthorization voor citations/downloads.
## Operations isolation
Iedere workspace-scoped job draagt expliciete ownership: `jobs.jobs.workspace_id`
is een echte kolom (migratie 0018), geen veld in `payload`. Elke lijst, teller,
detailpagina en mutatie filtert daarop in de query zelf --- nooit op rijen die al
opgehaald zijn.
- `PLATFORM_ADMIN` krijgt de expliciete globale scope (`workspace_id=None`) en
ziet dat ook op het scherm staan (`Scope: All workspaces`).
- `WORKSPACE_ADMIN` en `AUDITOR` zijn gebonden aan `principal.workspace_id`, voor
lijst, statustellers, filters, source-namen, detail en retry. `AUDITOR` is
read-only: retry vereist een rol uit `_RETRY_ROLES`.
- Een job zonder ownership (`workspace_id IS NULL`, alleen mogelijk voor rijen van
vóór 0018 waarvan de eigenaar niet betrouwbaar vast te stellen was) faalt
gesloten: onzichtbaar en onmuteerbaar voor iedere workspace-scoped principal,
uitsluitend inspecteerbaar door een platform admin. Er is nergens een
`payload.get("workspace_id") or principal.workspace_id`-fallback; die kende een
ownerloze job toe aan wie er toevallig naar keek.
- Tellers zijn ook tenantdata. Dashboard- en System Health-queuecijfers gebruiken
dezelfde scope als de Jobs-lijst.
- Ook de operatorfilters (status, type) en de paginering zijn predicaten van
diezelfde query (`JobListFilter` --- migratie 0019 voegt de bijbehorende index
toe). Er wordt dus geen bredere set opgehaald dan getoond wordt: elke rij die
dit proces binnenkomt is er één die deze principal mag zien. De vijf tellers
boven de tabel blijven bewust een scope-brede samenvatting van de wachtrij en
het scherm zegt dat er ook bij.
- Retry dwingt ownership af in het `UPDATE` zelf, niet in een voorafgaande read:
een cross-tenant mutatie die alleen onder concurrency lukt is nog steeds een
cross-tenant mutatie. Een geweigerde toegang of retry wordt vastgelegd als
`SECURITY_FAILURE` met actor, workspace, actie, doel en reden --- zonder payload.
Nieuwe jobs kunnen niet ownerloos ontstaan: `JobService.enqueue` eist
`workspace_id` en `PostgresJobRepository.enqueue` weigert een `Job` zonder.
## Filesystem-backed sources
Een Folder-source, en de lokale checkout root van een Git-source, geven de worker
een leesprimitief op de host: alles onder dat pad wordt vindbare content. Dat is
iets anders dan content beheren, dus het vereist `FILESYSTEM_SOURCE_MANAGE`
*bovenop* `SOURCE_MANAGE`, bij zowel aanmaken als bewerken (bewerken is precies
hoe een goedgekeurde source op een andere directory gericht wordt).
Gekozen model: **alleen `PLATFORM_ADMIN`**. `RAGCORE_SOURCE_ROOTS` is één
deployment-brede lijst zonder per-workspace mapping, dus een pad binnen de
allowlist kan prima het corpus van een andere tenant zijn; een workspace admin met
dit recht zou workspace B kunnen lezen door er een source op te richten. Zolang
roots niet per workspace geconfigureerd zijn, is het kiezen van een serverpad een
deploymentbeslissing en hoort die bij de rol die de deployment bezit. Per-workspace
roots (het sterkere self-service model) blijven mogelijk als self-service
filesystem sources later echt nodig blijken.
Alleen de gevoelige kinds zijn beperkt: `SOURCE_MANAGE` blijft ongewijzigd voor
Editors en Space Managers, en upload-sources worden er niet moeilijker door.
Autorisatie en sandbox zijn twee onafhankelijke poorten, allebei altijd vereist:
- `RAGCORE_SOURCE_ROOTS` blijft lexicaal afgedwongen bij opslaan, en volledig
geresolved (symlinks gevolgd) in worker en connector vlak voor iedere read. Een
pad buiten elke root wordt geweigerd --- ook voor een platform admin. Zonder
geconfigureerde roots kan geen enkele filesystem-source bestaan.
- De source mounts horen read-only te zijn. Dat is een security-invariant, niet
alleen een aanbeveling: het is wat het resterende TOCTOU-venster tussen
padvalidatie, `stat` en `open` onschadelijk maakt. Zijn de directories muteerbaar
door niet-vertrouwde actoren, dan is die aanname geschonden.
## Network
Alleen app achter reverse proxy. PostgreSQL/Qdrant/worker op internal network. Geen debug/adminpoorten publiek. Egress voor connector/modelworkers zo beperkt mogelijk.
## Content
MIME sniffing, allowlists, size/time/depth limits, archive-bombdetectie, quarantine, sandboxing waar haalbaar, geen macro/scriptuitvoering en read-only source mounts.
## Secrets
Environment/secrets mount, geen plaintext in database/logs/evidence, redaction processor, onafhankelijke token pepper en rotatieprocedure.
## Abuse prevention
Rate limits per principal/application, request/body/token/context limits, bounded concurrency, job quotas en circuit breakers.
## Audit
Append-only events voor auth, grants, source changes, publication, modelroute, adminacties en security failures. Querycontentlogbeleid is per space configureerbaar.