Skip to content

Policy language reference

Neksur Access policies are written in CEL (Common Expression Language, cel-go). This page is the complete reference for the evaluation environment, helper functions, and policy kinds. For a task-oriented walkthrough with examples, see the guide Author Access policies.

  • A policy is a single boolean CEL expression.
  • true → allow; false → deny.
  • Policies are compiled once and cached by (policy_id, policy_text).
  • Evaluation is fail-closed: a compile error, evaluation error, non-boolean result, or panic rejects the operation (503 on the write path) — it never allows-by-default.
  • On the write path, first deny wins across all policies governing a table.

Three variables are in scope. All are map-shaped; access fields with dot or index notation.

The loaded Iceberg table metadata.

FieldTypeNotes
table.namestringTable name.
table.namespacestringNamespace.
table.schema.fieldslistEach {name, type}.
table.partition_spec.fieldslistPartition spec fields.
table.propertiesmapTable properties.
table.snapshotslistSnapshot history.

The proposed change (an Iceberg UpdateTableRequest).

FieldTypeNotes
commit.updateslistEach has action (e.g. add-column, remove-snapshot) and, where relevant, snapshot.committed_at_ms (int64).
commit.requirementslistIceberg table requirements asserted by the commit.
commit.location_regionstringFrom the request region header (used by residency/partition rules).

The authenticated caller.

FieldTypeNotes
principal.substringSubject / user ID.
principal.roleslist<string>Roles.
principal.claimsmapOIDC token claims.
FunctionReturnsPurpose
manifest.has_column(table, "name")boolWhether the schema contains a column.
manifest.has_partition(table, "spec")boolWhether a partition spec is present.
manifest.partition_spec(table)map<string,string>The active partition spec.
manifest.classification_satisfied(table, "^pattern$", "tag")boolWhether every column matching the regex carries the required classification tag.
principal.role(principal, "role")boolRole membership check.
principal.attribute(principal, "attr")stringABAC attribute, resolved in three layers: OIDC claim → graph HAS_ATTRIBUTE edge → tenant default.
location.region(commit)stringThe commit’s region.

The kind selects the graph relationship that attaches a policy to a table and where it is enforced:

KindRelationshipEnforced atPurpose
schemaSCHEMA_GOVERNSwrite (gateway)Schema constraints (required/forbidden columns).
write_aclWRITE_GOVERNSwrite (gateway)Who may write.
retentionRETAINSwrite (gateway)Minimum retention before snapshot removal.
residencyRESIDENCY_GOVERNSwrite (gateway)Allowed write regions.
classificationCLASSIFICATION_GOVERNSwrite (gateway)Required column classification.
row_filterread (proxy / BI / MCP)Restrict which rows a reader sees.
column_maskread (proxy / BI / MCP)Mask/redact/tokenize columns.
// schema: forbid a column
!manifest.has_column(table, "ssn")
// write_acl: by subject
principal.sub in ["alice", "bob"]
// write_acl: by role
principal.role(principal, "data_engineer") || principal.role(principal, "dba")
// retention: no removal of snapshots newer than a cutoff (epoch ms)
commit.updates.all(u,
u.action != "remove-snapshot" || u.snapshot.committed_at_ms < 1672531200000)
// residency: allowed regions only
location.region(commit) in ["us-east-1", "us-west-2"]
// classification: every pii_* column must be tagged sensitive
manifest.classification_satisfied(table, "^pii_.*", "sensitive")
// row_filter: reader's region must match the table's
principal.attribute(principal, "region") == table.properties["region"]
// column_mask: privileged role sees unmasked
principal.role(principal, "pii_reader")
Terminal window
neksur-cli policy compile ./policy.cel

0 = clean; 1 = CEL/binding error; 2 = file/usage error.