Zum Hauptinhalt springen
connic
Starte kostenlos
Build

Zugriffsregeln

Lege fest, was die Besucher einer App und die Tools eines Agenten in Datenbank, Dateien und Retrieval eines Environments lesen und ändern dürfen, in Apps auch in Runs, Sessions und Freigaben. Die Regeln laufen bei jeder Anfrage und jedem Tool-Aufruf, und alles ohne Regel ist verboten.

Zuletzt aktualisiert

Apps und Agenten nutzen dieselben Zugriffsregeln. access in apps/<key>.yaml oder agents/<name>.yaml enthält eine Regel pro Ressource und Operation: einen Ausdruck darüber, wer fragt, und über den Datensatz.

  • Die Regeln einer App prüfen jede Anfrage an ihre Data API. Eine App ohne access kann keine Daten lesen oder ändern. Der Tab Access der App im Dashboard zeigt die deployten Regeln.
  • Die Regeln eines Agenten prüfen jeden Aufruf der Database Tools, File Tools und Retrieval Tools, auch wenn deine eigenen Tools sie über connic.tools aufrufen. Ohne access nutzen diese Tools alle Daten im Environment des Agenten. Siehe Agenten.

Regeln

apps/portal.yaml
lookups:
  member:
    collection: members
    where: doc.email == user.email
access:
  database:
    tickets:
      read: doc.author_id == user.id or member.role == "agent"
      insert: user.signed_in == true
      update: doc.author_id == user.id and doc.status == "open"
      delete: member.role == "admin"
      set:
        author_id: user.id
        status: '"open"'
  files:
    attachments:
      read: member.role == "agent"
  runs:
    read: run.context.end_user.id == user.id
  retrieval:
    help:
      search: true
agents/support.yaml
access:
  database:
    "*":
      read: true
    tickets:
      read: user == null or doc.author_id == user.id
      insert: true
      update: user == null or doc.author_id == user.id
  files:
    uploads:
      read: file.session_id == session.id
      write: true
  retrieval:
    help:
      search: true
    notes:
      search: true
      store: true
RessourceKeysAppsAgenten
databaseName der Collection oder "*"read, insert, update, delete, set, fieldsread, insert, update, delete, set, fields
filesOrdner oder "*"read, write, update, delete, setread, write, update, delete, set
retrievalNamespace oder "*"searchsearch, store, delete
runsread, cancel
sessionsread, delete
approvalsread, decide

Eine fehlende Ressource, Collection, ein fehlender Ordner, Namespace oder eine fehlende Operation ist verboten. Auch YAML-true und false sind Regeln: read: true lässt jeden lesen. Setze eine Regel, die mit einem Anführungszeichen beginnt, in Quotes, etwa read: '"finance" in user.groups', damit YAML sie als Text liest.

Der Eintrag "*" gilt für jede Collection, jeden Ordner und jeden Namespace ohne eigenen Eintrag. Ein benannter Eintrag hat Vorrang, auch ein leerer: secrets: {} neben "*": {read: true} verbietet jede Operation auf secrets. Setze den Key in Quotes, denn ein bloßes * liest YAML als Alias.

Namen

Jede Regel sieht user, die Lookups und den Datensatz ihrer Operation; Regeln von Agenten sehen außerdem context und session. Ein Name, der nicht verfügbar ist, lässt connic lint scheitern.

NameVerfügbar inFelder
userjede RegelApps: der Besucher mit id, email, name, groups, claims, signed_in. Agenten: der App-Besucher, für den der Run läuft, mit denselben Feldern, oder null
contextRegeln von Agentender Kontext des Runs
sessionRegeln von Agentenid der aktuellen Session des Agenten; null ohne Session
<lookup>jede Regel außer dem where eines Lookupsdie Felder des Dokuments plus id, created_at, updated_at; null, wenn nichts gefunden wurde. Mit values: eine Liste
docdatabase read, update, delete, fieldsdie gespeicherten Felder plus id, created_at, updated_at
newdatabase insert, update; files write, updatedas Dokument oder die Datei nach dem Schreiben, mit den Feldern aus set; siehe So wirken die Regeln
filefiles read, update, deletepath, folder, name, size, mime_type, metadata, session_id, created_at, updated_at
runruns read, cancel in Appsid, agent, status, context, input, output, queued_at, ended_at, duration_ms
sessionsessions read, delete in Appsid, agent, state, created_at, updated_at
approvalapprovals read, decide in Appsid, agent, tool, params, status, context (der Kontext des Runs), created_at

In Apps ist user der Besucher; was id, groups und claims in jedem Modus enthalten, steht unter Anmeldung. run.input und run.output lassen sich als JSON lesen, etwa run.input.order_id. Runs, die eine App startet, tragen den Besucher in run.context.end_user, Freigaben in approval.context.end_user.

In Agenten ist user der Besucher der App, deren Anfrage den Run gestartet hat, auch in den Agenten, die dieser Run mit trigger_agent startet. connic übernimmt ihn aus der signierten App-Anfrage, Middleware und Tools können ihn also nicht ändern. Runs ohne App-Besucher, etwa per Cron, Webhook oder aus dem Dashboard, haben user null.

Agenten

Regeln in agents/<name>.yaml legen fest, was die eingebauten Tools des Agenten dürfen, egal ob das Modell sie aufruft oder deine eigenen Tools über connic.tools. Ein verbotener Aufruf liefert statt eines Ergebnisses einen Fehler, und Listen und Zählungen sehen nur erlaubte Datensätze.

  • Database Tools nutzen die Regeln unter database. db_upsert braucht insert und update und wird abgelehnt, wenn sein Filter nur Dokumente trifft, die die Regeln verbergen.
  • File Tools nutzen die Regeln unter files, ebenso Downloads des Browsers in Dateien, Uploads des Browsers aus Dateien, Dateien, die retrieval_store importiert, und Freigabelinks in Ergebnissen von retrieval_query.
  • Retrieval Tools nutzen die Regeln unter retrieval: search für retrieval_query, store für retrieval_store und delete für retrieval_delete. Eine Suche ohne Namespace braucht den Eintrag "*".
  • Sobald ein Agent access hat, scheitert connic lint, wenn er ein eingebautes Tool nutzt, dessen Ressource keine Einträge hat, denn jeder Aufruf wäre verboten. Jede Ressource nimmt bis zu 100 Einträge.
  • Regeln auf user verbieten Runs ohne Besucher. Mit user == null or ... lässt du diese Runs durch. Ein set-Wert, der user liest, verbietet das Schreiben, wenn es keinen Besucher gibt.
  • lookups steht in der Agent-Datei neben access. Ihr where kann auch context und session nutzen, und ein Lookup darf nicht context heißen.

Das Deployment prüft die Regeln von Agenten wie die von Apps und scheitert mit der Agent-Datei und dem Pfad der Regel. Für Agenten mit den älteren Einstellungen siehe database, retrieval und files ersetzen.

Syntax

Regeln nutzen die Ausdruckssprache von connic, dieselbe wie Approval-Regeln und bedingte Tools: Vergleiche, and, or, not, in, not in, Pfade mit Punkten oder Subscripts und Literale, ohne Funktionsaufrufe und Arithmetik, bis zu 2.000 Zeichen. Weil connic den Teil einer Regel, der den Datensatz betrifft, in einen Abfragefilter übersetzt, gelten für die Datensatznamen doc, file, run, session und approval diese Grenzen:

  • Vergleiche ein Feld mit einem Wert, etwa doc.done == true. Ein bloßes doc.done wird abgelehnt.
  • Eine Regel kann weder zwei Felder des Datensatzes noch ein Feld des Datensatzes mit new vergleichen.
  • In update-Regeln der Datenbank nutzt du new über seine Felder, etwa new.status, und vergleichst jedes mit einem Wert: Zwei Felder von new lassen sich nicht vergleichen.
  • doc.id, file.session_id, run.id, run.status, approval.id und approval.status erlauben nur ==, !=, in und not in.
  • Feldnamen dürfen nicht mit _ oder $ beginnen und keine Punkte enthalten. Die gespeicherten Systemfelder heißen id, created_at und updated_at. Dasselbe gilt für die Namen unter set und fields und für jeden Teil des values-Pfads eines Lookups, der aus mehreren Teilen bestehen kann, etwa team.id. Andere Namen lehnen connic lint und das Deployment ab.

Außerdem gelten für jede Regel diese Grenzen:

  • is und is not funktionieren nur mit den Literalen null, true und false.
  • Ein Vergleich kann keine andere Bedingung als Wert nehmen, deshalb wird (doc.done == true) == false abgelehnt. Verknüpfe Vergleiche mit and, or und not.
  • Regeln für Datenbank und Dateien sowie das where von Lookups werden zu Datenbankfiltern mit diesen Grenzen: 10 Verschachtelungsebenen, von denen der Filter, den connic um Zugriffsregeln legt, eine belegt, 100 Zweige pro and oder or, 256 Terme und 1.000 Werte pro in-Liste.

connic lint prüft Syntax und Namen. Bei öffentlichen Apps warnt das Deployment im Log vor Regeln, die jeden Besucher alles lesen lassen, Schreibzugriffe nicht vom Besucher abhängig machen oder Uploads ohne Größengrenze erlauben. Das Deployment prüft, ob connic jede Regel durchsetzen kann, und scheitert mit dem Pfad der Regel, etwa mit use is and is not only with null, true or false oder it compiles to a database filter that is too large: <reason>:

Deployment-Log
App validation failed:
  - apps/portal.yaml: access.database.tickets.read: can't compare two fields of doc

So wirken die Regeln

Bei jeder Anfrage und jedem Tool-Aufruf wertet connic alle Teile einer Regel aus, die den gespeicherten Datensatz nicht betreffen: user, die Lookups, new und in Agenten context und session. Was über den Datensatz übrig bleibt, wird zu einem Filter, den connic dem Filter des Aufrufers hinzufügt. Listen, Zählungen, Summen, Updates und Löschungen erreichen deshalb nur erlaubte Datensätze.

  • Eine Regel, die unabhängig vom Datensatz falsch ist, lehnt die Anfrage ab, in Apps mit 403. Bei einem einzelnen Run, einer Datei, Session oder Freigabe antwortet ein Datensatz, den die Regel nicht erlaubt, mit 404, als gäbe es ihn nicht.
  • insert und write bei Dateien prüfen new vor dem Schreiben, also das Dokument oder den Upload mit den Feldern aus set. Jedes Dokument eines Inserts muss die Regel erfüllen, sonst wird nichts eingefügt.
  • update in der Datenbank ändert nur die Dokumente, die der doc-Teil erlaubt. new ist jedes Dokument nach der Änderung: die Felder, die das Update schickt, und für alle anderen die gespeicherten Werte. Ein Feld, das das Update auf null setzt, fehlt in new. update: new.status == "open" lässt also ein Update des Titels bei offenen Tickets durch.
  • update bei Dateien sieht die Datei vor der Änderung als file und danach als new. Wer eine Datei in einen anderen Ordner verschiebt, braucht zusätzlich dessen write-Regel.
  • Ein Upsert braucht insert und update. Er ändert das erste Dokument, das die Regeln ändern lassen, oder fügt eines ein, das die Insert-Regel erlaubt. Trifft sein Filter nur Dokumente, die die Regeln nicht ändern lassen, wird er abgelehnt.
  • Eine Regel kann für eine einzelne Anfrage trotzdem einen zu großen Filter ergeben, etwa doc.team in user.groups für jemanden in mehr als 1.000 Gruppen. Die Anfrage scheitert dann, in Apps mit 500 An access rule makes a database filter that is too large: <reason>. Simplify the rule or the values it compares with.

Fehlende Werte und null

Ein Vergleich ist unbestimmt, wenn eine seiner Seiten fehlt, etwa ein nicht vorhandenes Feld oder ein Feld eines Lookups ohne Treffer, oder wenn sie null ist. not lässt Unbestimmtes unbestimmt. and ist falsch, sobald ein Teil falsch ist, or ist wahr, sobald ein Teil wahr ist, und sonst macht ein unbestimmter Teil das Ergebnis unbestimmt. Eine Regel, die unbestimmt endet, verbietet. not (member.blocked == true) verbietet deshalb einem Besucher ohne Member-Dokument den Zugriff.

Nur ein Vergleich mit dem Literal null prüft auf null. doc.x == null und doc.x is null sind wahr, wenn das Feld existiert und null ist, falsch, wenn es einen anderen Wert hat, und unbestimmt, wenn es fehlt; != und is not liefern für ein vorhandenes Feld das Gegenteil. Ein Lookup ohne Treffer gilt als vorhanden und null, member == null ist also wahr, ebenso user == null in einem Run eines Agenten ohne Besucher. doc.status != "archived" trifft nur Dokumente, deren status einen anderen Wert hat; mit or doc.status == null kommen die hinzu, bei denen er null ist.

Vergleiche

  • Werte werden wie JSON verglichen. Jeder Typ ist nur sich selbst gleich: true ist nicht 1 und "1" nicht 1, aber 1 ist gleich 1.0.
  • <, <=, > und >= vergleichen zwei Zahlen oder zwei Texte, Texte nach Codepoints. Jedes andere Paar ist unbestimmt.
  • x in list prüft die Einträge der Liste mit derselben typgenauen Gleichheit, und eine leere Liste ergibt false. x in object prüft die Schlüssel des Objekts. x in text ist nur wahr, wenn x dem ganzen Text entspricht, nie für einen Teil davon; "vip" in doc.tags passt also zu einer Liste von Tags. In allem anderen ist in unbestimmt.
  • Zeitstempel wie doc.created_at, file.updated_at, run.queued_at oder approval.created_at werden als Zeitpunkte mit ISO-8601-Text verglichen, etwa doc.created_at >= "2026-01-01T00:00:00Z". Text ohne Zeitzonen-Offset gilt als UTC.
  • Ein einzelner Wert als Bedingung, etwa user.signed_in, muss true oder false sein; alles andere ist unbestimmt.

set

set listet Felder, die connic selbst schreibt, über das hinweg, was der Aufrufer geschickt hat. Ein einfacher Wert wird beim Insert geschrieben. Die Form mit value und writes schreibt zusätzlich bei jedem Update oder nur dann. Unter files schreibt set Metadaten: Insert heißt dort Upload oder file_write, Update heißt jedes Update einer Datei, auch eine Umbenennung.

apps/portal.yaml
access:
  database:
    tickets:
      set:
        author_id: user.id            # beim Insert
        updated_by:
          value: user.id
          writes: [insert, update]
  files:
    uploads:
      set:
        uploaded_by: user.id          # Metadaten jedes Uploads

Jeder Wert ist ein Ausdruck über user und die Lookups, in Agenten auch über context und session: author_id: user.id hält fest, wer ein Dokument geschrieben hat, und status: '"open"' schreibt einen festen Text. Lässt sich ein Wert nicht auswerten, etwa weil sein Lookup nichts gefunden hat, wird das Schreiben abgelehnt. Beim Insert überschreibt connic die set-Felder, die der Aufrufer geschickt hat, und ein Insert, der ein Feld schickt, das connic nur beim Update schreibt, scheitert. Ein Update, das irgendein set-Feld nennt, scheitert, in Apps mit 400 Field 'author_id' is set by the app and can't be changed.

fields

fields enthält eine Regel pro Feld der obersten Ebene einer Collection. Die Regel sieht doc und kann deshalb vom Dokument abhängen und davon, wer fragt.

apps/support.yaml
access:
  database:
    tickets:
      read: doc.author_id == user.id or member.role == "agent"
      update: doc.author_id == user.id or member.role == "agent"
      fields:
        internal_notes: member.role == "agent"
  • Lesezugriffe liefern das Feld nur aus Dokumenten, für die seine Regel gilt. Alle anderen Dokumente kommen ohne das Feld zurück.
  • Die Regel wird am Dokument so geprüft, wie es zurückkommt. Lässt die fields-Liste einer Suche ein Feld weg, das die Regel liest, fehlt auch das Feld, das sie schützt. Nimm also die Felder mit auf, die deine Feldregeln lesen.
  • Ein Filter, eine Sortierung oder ein Distinct auf einem Feld, dessen Regel nicht für jedes Dokument gilt, wird abgelehnt. So lässt sich ein verborgenes Feld nicht über die Suche nach seinem Wert herausfinden.
  • Ein Insert, der das Feld schickt, braucht seine Regel für das neue Dokument. Ein Update, das das Feld schickt, ändert nur die Dokumente, für die seine Regel gilt.
  • Felder, die set schreibt, brauchen hier keine Regel. Felder ohne Regel unterliegen nur den Regeln der Collection.

Lookups

Ein Lookup findet ein Dokument in einer Collection für Regeln, die von gespeicherten Daten abhängen, etwa der Rolle eines Mitglieds. collection nennt die Collection, und where ist ein Ausdruck über doc und user, in Agenten auch über context und session. connic führt einen Lookup nur aus, wenn eine Regel ihn nutzt, höchstens einmal pro Anfrage oder Tool-Aufruf, und nimmt das älteste passende Dokument. Die Collection des Lookups braucht keine eigene Zugriffsregel, und der Aufrufer kann sie nur lesen, wenn eine Regel es erlaubt.

Mit values ist ein Lookup stattdessen die Liste der Werte eines Felds aus allen passenden Dokumenten, etwa für die Mitgliedschaft in mehreren Teams. Dokumente ohne das Feld tragen nichts bei. Trifft ein Lookup mehr als 1.000 Dokumente, scheitert die Anfrage mit The lookup <name> found more than 1000 documents. Narrow its where.

apps/projects.yaml
lookups:
  teams:
    collection: memberships
    where: doc.user_id == user.id
    values: team_id
access:
  database:
    projects:
      read: doc.team_id in teams

Lookup-Namen sind Bezeichner wie member und dürfen nicht user, doc, new, file, run, session, approval, true, false oder null heißen, in Agenten auch nicht context.

Ordner

Die Keys unter files sind Ordner, mit oder ohne Schrägstriche. Eine Regel gilt für ihren Ordner und alles darunter, und der genaueste Ordner gewinnt: Mit Regeln für reports und reports/private folgen Dateien in reports/private/2026 der Regel von reports/private. Der Eintrag "*" gilt für den ganzen Baum samt Wurzelordner, überall dort, wo kein anderer Eintrag greift.

Eine Liste zeigt eine Ebene: die Dateien des Ordners, die seine Regel den Aufrufer lesen lässt, und die Unterordner mit mindestens einer Datei, die der Aufrufer nach der Regel dieser Datei lesen darf. Dateien unter einem Ordner, dessen Regel das Lesen verbietet, bleiben verborgen, außer ein genauerer Ordner darunter hat eine Regel, die sie erlaubt. Ein Ordner, für den kein Eintrag gilt, liefert keine Dateien, aber die Unterordner mit lesbaren Dateien. Nur wenn keine Regel auf oder unter dem Ordner das Lesen erlauben kann, wird die Liste abgelehnt.

Retrieval-Namespaces

Die Keys unter retrieval sind Namespaces in Retrieval, etwa help oder docs.public. Ein Namespace folgt den Regeln des genauesten Eintrags, der ihn enthält, und "*" gilt für den Rest. Die Regeln sehen, wer fragt, und die Lookups, nicht die Einträge.

Eine Suche liefert Textstellen aus dem durchsuchten Namespace und allen Namespaces darunter, sie umfasst diese also unabhängig von deren eigenen Regeln: Sind help und help.internal aufgeführt, liefert eine Suche in help auch Textstellen aus help.internal. Lege Inhalte für unterschiedliche Zielgruppen in getrennte Namespaces, etwa public.help und internal.help. store und delete folgen dem Eintrag des Namespace, in den sie schreiben. Apps suchen immer in einem Namespace, Einträge ohne Namespace lassen sich aus einer App also nicht durchsuchen.

Öffentliche Besucher

In einer öffentlichen App ist user.signed_in false, user.email und user.name sind null, user.groups ist leer, und user.id ist die Besucher-ID des Browsers.

Vergleiche mit der E-Mail-Adresse eines öffentlichen Besuchers sind unbestimmt. doc.owner == user.email trifft deshalb kein Dokument, auch keines, dessen owner null ist, und ein Lookup mit where: doc.email == user.email findet nichts.

connic leitet die Besucher-ID für jede App getrennt aus einem Secret im Cookie des Browsers ab. Wer die ID eines anderen kennt, kann also nicht in dessen Namen handeln. Die ID ändert sich, wenn jemand die Cookies löscht, und jeder kann sich eine neue holen. Regeln auf user.id passen zu Daten, die zu einem Browser gehören, etwa einem Entwurf, nicht zu Daten, die ein Konto brauchen.

Öffentliche Formulare schützen

Die Formulare einer öffentlichen App kann jeder absenden, auch Bots. Schreibzugriffe über die Data API prüft connic gegen deine Regeln, aber ohne Middleware, eine Challenge lässt sich dort also nicht prüfen. Für Formulare, die Bots anziehen, schützt du das Formular selbst und lässt einen Agenten schreiben:

  1. Binde einen Challenge-Dienst wie ein CAPTCHA in das Formular ein. Er fügt dem Absenden ein Token hinzu.

  2. Schicke das Formular an einen Sync-Webhook-Connector mit apps_only: true unter /_connic/c/<key>, statt es über die Data API einzufügen.

  3. Prüfe das Token in der Middleware des Agenten beim Challenge-Dienst und stoppe den Run, wenn die Prüfung scheitert. Danach schreibt der Agent mit Database Tools.

  4. Lass insert in den Regeln der Collection in der App weg, damit der Browser nicht an der Prüfung vorbei schreiben kann.

middleware/contact-form.py
import os

import httpx
from connic import StopProcessing


async def before(content, context):
    token = context["payload"].get("challenge_token")
    async with httpx.AsyncClient(timeout=10) as client:
        response = await client.post(
            os.environ["CHALLENGE_VERIFY_URL"],
            data={"secret": os.environ["CHALLENGE_SECRET"], "response": token},
        )
    if not response.json().get("success"):
        raise StopProcessing("Die Formularprüfung ist fehlgeschlagen. Lade die Seite neu und versuche es noch einmal.")
    return content

Wie die Prüfung aussieht, hängt vom Challenge-Dienst ab; das Beispiel schickt das Token und ein Secret an die Prüf-URL des Dienstes, beide als Variablen gespeichert. StopProcessing beendet den Run, bevor der Agent startet, und das Formular bekommt die Meldung als Ausgabe des Runs. Ein rate_limit am Connector begrenzt, wie viele Runs das Formular pro Minute starten kann. connic prüft Challenges nicht selbst.

database, retrieval und files ersetzen

Agenten können ihre Tools noch mit den älteren Einstellungen database, retrieval und files beschränken. Diese Einstellungen sind veraltet, und connic setzt sie als die Zugriffsregeln unten durch. connic lint warnt davor und gibt den passenden access-Block aus, den du an ihrer Stelle einfügst, und das Deployment warnt im Log. Ein Agent kann nicht gleichzeitig access und die älteren Einstellungen haben.

Ältere EinstellungZugriffsregeln
database, files oder retrieval fehlt neben den anderenein Eintrag "*" mit allen Operationen
keine collections, folders oder namespaces aufgeführtdie Einstellungen landen in einem Eintrag "*"
collections: [orders]orders: read, insert, update, delete
prevent_write: truedatabase ohne insert und update, files ohne write und update, retrieval ohne store
prevent_delete: trueohne delete
session_only: trueread, update, delete: file.session_id == session.id; write: session.id != null

Eine Einstellung an einem Eintrag hat Vorrang vor der obersten Ebene, und verschachtelte Namespaces folgen dem genauesten Eintrag.

Beispiele

Eigene Datensätze

Angemeldete Besucher sehen und ändern nur die Notizen, die sie angelegt haben. set trägt beim Insert den Besitzer ein, und Updates können ihn nicht ändern.

apps/notes.yaml
access:
  database:
    notes:
      read: doc.owner_id == user.id
      insert: user.signed_in == true
      update: doc.owner_id == user.id
      delete: doc.owner_id == user.id
      set:
        owner_id: user.id

Admins über einen Lookup

In einer App mit Anmeldung hält eine Collection members, gepflegt von Agenten oder importiert, Kunde und Rolle jeder Person. Kunden sehen ihre eigenen Bestellungen, Admins sehen und ändern alle.

apps/orders.yaml
lookups:
  member:
    collection: members
    where: doc.email == user.email
access:
  database:
    orders:
      read: doc.customer_id == member.customer_id or member.role == "admin"
      update: member.role == "admin"

Ein Agent im Auftrag eines Besuchers

Die Bestell-App von oben ruft einen Support-Agenten auf. Startet ein Besucher den Run, liest und ändert der Agent nur die Bestellungen dieses Kunden. Runs per Cron oder Webhook, ohne Besucher, erreichen jede Bestellung.

agents/order-support.yaml
tools:
  - db_find
  - db_update
lookups:
  member:
    collection: members
    where: doc.email == user.email
access:
  database:
    orders:
      read: user == null or doc.customer_id == member.customer_id
      update: user == null or doc.customer_id == member.customer_id

Dateien pro Session

Jeder Kunde hat eine eigene Session, und der Agent sieht nur die Uploads, die in der aktuellen geschrieben wurden. Vorlagen gelten für alle Sessions und lassen sich nur lesen, und gelöscht wird nichts.

agents/support.yaml
session:
  key: context.customer_id
tools:
  - file_list
  - file_read
  - file_write
access:
  files:
    uploads:
      read: file.session_id == session.id
      write: true
      update: file.session_id == session.id
    templates:
      read: true

Veröffentlichte Inhalte in einer öffentlichen App

Jeder kann veröffentlichte Artikel lesen. Entwürfe bleiben verborgen, und niemand kann schreiben.

apps/help.yaml
auth:
  mode: public
access:
  database:
    articles:
      read: doc.status == "published"

Dateien nach Gruppe und Metadaten

Die Gruppe billing liest Rechnungen. Jeder Besucher lädt PDFs bis 10 MB nach uploads hoch, markiert mit seiner eigenen ID aus /_connic/me, und sieht nur seine eigenen Uploads. Mit set: {uploaded_by: user.id} unter uploads schreibt connic die Markierung selbst.

apps/portal.yaml
access:
  files:
    invoices:
      read: '"billing" in user.groups'
    uploads:
      read: file.metadata.uploaded_by == user.id
      write: >-
        new.metadata.uploaded_by == user.id
        and new.mime_type == "application/pdf"
        and new.size <= 10000000

Runs, die der Besucher gestartet hat

Besucher verfolgen die Runs, die sie über die Connectors der App gestartet haben, und brechen sie ab, solange sie warten oder laufen.

apps/portal.yaml
access:
  runs:
    read: run.context.end_user.id == user.id
    cancel: run.context.end_user.id == user.id and run.status in ["queued", "started"]

Freigaben für eine Gruppe

Die Gruppe finance sieht jede Freigabe des Environments und entscheidet über Erstattungen unter 5.000.

apps/finance.yaml
access:
  approvals:
    read: '"finance" in user.groups'
    decide: '"finance" in user.groups and approval.tool == "issue_refund" and approval.params.amount < 5000'

Jeder kann die Artikel in help und den Namespaces darunter über retrieval/search durchsuchen und ihre Originaldateien über files/download öffnen. In einer App mit Anmeldung beschränkt eine Regel wie search: '"support" in user.groups' die Suche auf eine Gruppe.

apps/help.yaml
auth:
  mode: public
access:
  retrieval:
    help:
      search: true
  files:
    retrieval/help:
      read: true