Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions examples/nhi-example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
# Non-Human Identity (NHI) + AI-agent reference configuration
# ===========================================================
# Demonstrates how a baton-sql config author declares the NHI ontology and AI
# agents so the engine emits the corresponding baton-sdk traits:
#
# K1 secret / credential -> map.traits.secret (SecretTrait)
# K2 service / system account -> map.traits.user.account_type (UserTrait.account_type)
# K3 non-human identity -> map.non_human_identity (NonHumanIdentityTrait, kind-agnostic)
# AI agent -> map.traits.agent (AgentTrait)
#
# Every field below is optional and additive: configs that omit them sync
# exactly as before. Column references and CEL expressions resolve against each
# query row, identical to the other examples.

app_name: NHI Reference Application

connect:
scheme: "postgres"
host: "${DB_HOST}"
port: "5432"
database: "${DB_NAME}"
user: "${DB_USER}"
password: "${DB_PASS}"

resource_types:
# K2 — service / system accounts.
# account_type maps to UserTrait.account_type: service | system | human (default).
service_account:
name: "Service Account"
description: "Machine accounts; classified service or system."
list:
query: |
SELECT id, username, kind FROM accounts
WHERE id > ?<Cursor> ORDER BY id ASC LIMIT ?<Limit>
map:
id: ".id"
display_name: ".username"
traits:
user:
# "service" -> ACCOUNT_TYPE_SERVICE, "system" -> ACCOUNT_TYPE_SYSTEM
account_type: ".kind"
login: ".username"
pagination:
strategy: "cursor"
primary_key: "id"

# K1 — secret / credential resources.
api_token:
name: "API Token"
description: "Long-lived API tokens issued by the platform."
list:
query: |
SELECT id, name, expires_at, last_used_at FROM api_tokens
WHERE id > ?<Cursor> ORDER BY id ASC LIMIT ?<Limit>
map:
id: ".id"
display_name: ".name"
traits:
secret:
# static_secret | asymmetric_key | certificate
credential_type: "'static_secret'"
# free-form "<platform>.<object>" descriptor
credential_detail: "'postgres.api_token'"
expires_at: ".expires_at"
last_used_at: ".last_used_at"
pagination:
strategy: "cursor"
primary_key: "id"

# K3 — non-human identity, attached alongside a primary (app) trait.
# NHI is kind-agnostic: non_human_identity is a sibling of traits, so the
# resource is both an app AND a non-human identity.
iam_role:
name: "IAM Role"
description: "Assumable roles modeled as app registrations / assumable roles."
list:
query: |
SELECT id, name, arn FROM iam_roles
WHERE id > ?<Cursor> ORDER BY id ASC LIMIT ?<Limit>
map:
id: ".id"
display_name: ".name"
traits:
app:
profile:
arn: ".arn"
non_human_identity:
# app_registration | assumable_role | managed_identity
nhi_type: "'assumable_role'"
nhi_detail: "'aws.iam_role'"
pagination:
strategy: "cursor"
primary_key: "id"

# AI agent — autonomous non-human actor that authenticates as an identity.
ai_agent:
name: "AI Agent"
description: "AI agents registered in the platform."
list:
query: |
SELECT id, name, state, identity_id, model FROM ai_agents
WHERE id > ?<Cursor> ORDER BY id ASC LIMIT ?<Limit>
map:
id: ".id"
display_name: ".name"
traits:
agent:
# ready (active, enabled) | disabled (inactive) | deleted
status: ".state"
# the identity the agent authenticates as (both fields required to set the ref)
identity_resource_type: "'service_account'"
identity_resource_id: ".identity_id"
profile:
model: ".model"
pagination:
strategy: "cursor"
primary_key: "id"
62 changes: 62 additions & 0 deletions pkg/bsql/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,28 @@ type ResourceMapping struct {
// Traits defines specific attribute mappings for various resource subtypes (e.g., user, role).
Traits *Traits `yaml:"traits" json:"traits"`

// NonHumanIdentity marks the resource as a non-human identity (K3). It is
// kind-agnostic: it attaches a NonHumanIdentityTrait annotation alongside
// whatever primary trait (if any) the resource carries, so it lives here as
// a sibling of Traits rather than inside it.
NonHumanIdentity *NonHumanIdentityMapping `yaml:"non_human_identity,omitempty" json:"non_human_identity,omitempty"`

// Annotations includes additional metadata such as entitlement immutability and external links.
Annotations *Annotations `yaml:"annotations" json:"annotations"`
}

// NonHumanIdentityMapping declares that a resource is a non-human identity (K3).
// Both fields are CEL expressions evaluated against the query row.
type NonHumanIdentityMapping struct {
// NhiType is the kind of non-human identity.
// Supported values: app_registration, assumable_role, managed_identity.
NhiType string `yaml:"nhi_type" json:"nhi_type"`

// NhiDetail is a free-form descriptor of the identity, conventionally
// "<platform>.<object>" (e.g. "aws.iam_role").
NhiDetail string `yaml:"nhi_detail,omitempty" json:"nhi_detail,omitempty"`
}

// Annotations holds extra metadata for resource or grant mappings.
type Annotations struct {
// EntitlementImmutable provides settings to mark an entitlement as immutable (e.g., cannot be revoked).
Expand All @@ -186,6 +204,50 @@ type Traits struct {

// User contains trait mappings for user resources.
User *UserTraitMapping `yaml:"user" json:"user"`

// Secret contains trait mappings for secret/credential resources (K1).
Secret *SecretTraitMapping `yaml:"secret,omitempty" json:"secret,omitempty"`

// Agent contains trait mappings for AI-agent resources.
Agent *AgentTraitMapping `yaml:"agent,omitempty" json:"agent,omitempty"`
}

// SecretTraitMapping defines attribute mappings for secret/credential resources (K1).
// All fields are CEL expressions evaluated against the query row.
type SecretTraitMapping struct {
// CredentialType classifies the secret.
// Supported values: static_secret, asymmetric_key, certificate.
CredentialType string `yaml:"credential_type" json:"credential_type"`

// CredentialDetail is a free-form descriptor of the credential,
// conventionally "<platform>.<object>" (e.g. "postgres.api_token").
CredentialDetail string `yaml:"credential_detail,omitempty" json:"credential_detail,omitempty"`

// ExpiresAt records when the credential expires (parsed using the DB engine's time format).
ExpiresAt string `yaml:"expires_at,omitempty" json:"expires_at,omitempty"`

// LastUsedAt records when the credential was last used.
LastUsedAt string `yaml:"last_used_at,omitempty" json:"last_used_at,omitempty"`
}

// AgentTraitMapping defines attribute mappings for AI-agent resources.
// String fields are CEL expressions evaluated against the query row.
type AgentTraitMapping struct {
// Status is the agent's lifecycle status.
// Supported values: ready (active, enabled), disabled (inactive), deleted.
Status string `yaml:"status,omitempty" json:"status,omitempty"`

// IdentityResourceType is the resource type of the identity the agent
// authenticates as. Required (together with IdentityResourceID) to set the
// agent's identity reference.
IdentityResourceType string `yaml:"identity_resource_type,omitempty" json:"identity_resource_type,omitempty"`

// IdentityResourceID is the resource id of the identity the agent
// authenticates as.
IdentityResourceID string `yaml:"identity_resource_id,omitempty" json:"identity_resource_id,omitempty"`

// Profile is a set of key-value pairs representing agent profile attributes.
Profile map[string]string `yaml:"profile,omitempty" json:"profile,omitempty"`
}

// UserTraitMapping defines attribute mappings specifically for user resources.
Expand Down
Loading
Loading