Skip to main content

Tegata Schema

Complete reference for the Tegata (手形) schema, version 0.1. A Tegata is a JSON document named <policy-id>.tegata.json that declares one authorization policy. This page documents every field, operator, and the fixed evaluation semantics.

For a guided introduction, see Quickstart and Add a Policy.

Canonical vs metadata

Every field is either canonical or metadata:

  • Canonical fields define the policy's meaning. They are compiled to Rego and included in the tegata_hash — the fingerprint you approve.
  • Metadata fields (descriptions, relationship label, the entire audit object) are for humans and audit trails. They are excluded from the hash and never compiled.

A practical consequence: reordering rules or rewriting a description does not change the tegata_hash; changing a role, action, condition, or effect does.


Top-level structure

additionalProperties: false. Required: tegata, policy, rules.

FieldTypeCanonicalNotes
tegatastringYesSchema version. Const "0.1".
policyobjectYesRequired id. See below.
attributesobject mapYesAttribute type declarations. See below.
auditobjectNoHuman/audit metadata. Never compiled. See below.
rulesarrayYesminItems: 1. See The rule object.

policy

FieldTypeCanonicalNotes
policy.idstringYeskebab-case ^[a-z][a-z0-9]*(-[a-z0-9]+)*$, maxLength: 64.
policy.descriptionstringNoFree text.

attributes

An object map (canonical). Keys match ^(subject|resource|environment|custom).<name...>; values are "string" | "integer" | "boolean". You only need to declare an attribute here when its type cannot be derived from rule literals — for example an attribute used only in a relationship.

audit

Metadata (never compiled). Fields:

FieldTypeNotes
source_textstringThe original natural-language requirement.
normalized_textstringA normalized restatement.
ambiguitiesarrayInterpretation notes. Each: code, message, optional related_rules[].

ambiguities[].code is one of: assumed_interpretation, missing_input, contradiction, unexpressible_delegated, exception_scope.


The rule object

additionalProperties: false. Required: id, effect, subject, actions, resource.

FieldTypeRequiredNotes
idstringYeskebab-case, maxLength: 64, unique within the file.
effectstringYes"allow" or "deny".
descriptionstringNoMetadata.
subjectobjectYesOptional roles. See below.
actionsarrayYesSee below.
resourceobjectYesRequired type. See below.
relationshipsarrayNoCross-entity comparisons. See Relationships.
conditionsarrayNoAttribute constraints. See Conditions.

subject

subject.roles is an optional, non-empty, unique array of snake_case identifiers. Roles are matched any-of (the subject matches if it holds any listed role). Omit roles to match any subject.

actions

Required. Either a non-empty, unique array of snake_case identifiers (matched any-of), or the exact wildcard ["*"].

resource

Required type: a snake_case identifier, or the wildcard "*".


Relationships

relationships is an optional array. This is the only place a cross-entity comparison (subject vs resource) is allowed.

FieldCanonicalNotes
labelNoHuman-readable name.
subject_attributeYesAn identifier.
opYesOne of eq, neq, gt, gte, lt, lte.
resource_attributeYesAn identifier.

Example — "the invoice's submitter is the requesting user":

{ "label": "own_submission", "subject_attribute": "user_id", "op": "eq", "resource_attribute": "submitted_by" }

Conditions

conditions is an optional array. Each condition is a discriminated union on op. The key is a scoped key: subject.*, resource.*, environment.*, or custom.*.

Familyop valuesValue fieldNotes
Scalareq, neqvalue (literal)Equality / inequality.
Orderinggt, gte, lt, ltevalue (integer or string)Not boolean.
Setin, not_invalues (non-empty, unique array of literals)Membership in a set.
Array membershipcontains, not_containsvalue (literal)Membership in an array attribute.
Existenceexists, not_existsNo value.

Example:

{ "key": "resource.amount", "op": "lte", "value": 500000 }

Identifiers and literals

  • Identifiers (roles, actions, resource types, attribute names) are snake_case.
  • Literals are string, integer, or boolean.
  • Integers only — no floats in v0.1. Amounts and thresholds are integers (e.g. JPY as an integer).

Evaluation semantics

These are fixed and non-configurable.

RuleBehavior
Within a ruleAll conditions (and relationships) are AND-ed.
Across same-effect rulesOR-ed — any matching rule of that effect matches.
allow vs denydeny overrides allow (Deny-First).
No matching allowdeny — Zero-Trust, default false.
roles / actionsMatched any-of.
Wildcards"*" matches everything.

Complete example

The canonical authz/invoice-access.tegata.json:

{
"tegata": "0.1",
"policy": {
"id": "invoice-access",
"description": "請求書の閲覧・削除・承認"
},
"attributes": {
"subject.user_id": "string",
"resource.submitted_by": "string"
},
"audit": {
"source_text": "従業員は自分が提出した請求書を閲覧できる。マネージャー・経理・管理者は全ての請求書を閲覧できる。マネージャーは50万円以内の請求書を承認できる。経理は金額によらず承認できる。管理者は請求書を削除できる。",
"ambiguities": [
{
"code": "assumed_interpretation",
"message": "「自分が提出した」を relationship(subject.user_id = resource.submitted_by)で表現した。代理提出・共同提出の概念はないものと仮定。",
"related_rules": ["allow-employee-view-own-invoice"]
},
{
"code": "assumed_interpretation",
"message": "「50万円以内」を resource.amount lte 500000(整数・JPY)と解釈した。境界値50万円ちょうどは承認可に含む。含まない意図なら lt に変更が必要。",
"related_rules": ["allow-manager-approve-invoice-within-limit"]
},
{
"code": "missing_input",
"message": "resource.amount / resource.submitted_by は請求書レコード(DB)から、subject.user_id はセッションから供給される前提。通貨はJPY単一通貨を仮定。",
"related_rules": ["allow-employee-view-own-invoice", "allow-manager-approve-invoice-within-limit"]
}
]
},
"rules": [
{
"id": "allow-employee-view-own-invoice",
"effect": "allow",
"description": "従業員は自分が提出した請求書を閲覧できる",
"subject": { "roles": ["employee"] },
"actions": ["view"],
"resource": { "type": "invoice" },
"relationships": [
{ "label": "own_submission", "subject_attribute": "user_id", "op": "eq", "resource_attribute": "submitted_by" }
]
},
{
"id": "allow-staff-view-invoice",
"effect": "allow",
"description": "マネージャー・経理・管理者は全ての請求書を閲覧できる",
"subject": { "roles": ["manager", "finance", "admin"] },
"actions": ["view"],
"resource": { "type": "invoice" }
},
{
"id": "allow-manager-approve-invoice-within-limit",
"effect": "allow",
"description": "マネージャーは50万円以内の請求書を承認できる",
"subject": { "roles": ["manager"] },
"actions": ["approve"],
"resource": { "type": "invoice" },
"conditions": [ { "key": "resource.amount", "op": "lte", "value": 500000 } ]
},
{
"id": "allow-finance-approve-invoice",
"effect": "allow",
"description": "経理は金額によらず請求書を承認できる",
"subject": { "roles": ["finance"] },
"actions": ["approve"],
"resource": { "type": "invoice" }
},
{
"id": "allow-admin-delete-invoice",
"effect": "allow",
"description": "管理者は請求書を削除できる",
"subject": { "roles": ["admin"] },
"actions": ["delete"],
"resource": { "type": "invoice" }
}
]
}

See also