Skip to content

Latest commit

 

History

History
858 lines (485 loc) · 42.4 KB

File metadata and controls

858 lines (485 loc) · 42.4 KB

API Reference

Packages

agents.nanohype.dev/v1alpha1

Package v1alpha1 contains API Schema definitions for the agents v1alpha1 API group.

Resource Types

AgentFleet

AgentFleet is a Platform-scoped composition of one or more agents on top of upstream kagent CRs. The scale subresource is deliberately omitted: kubectl scale would be ambiguous (min? max? per-agent?) for a fleet, so per-agent replica overrides live on AgentSpec.Replicas and fleet-wide behavior is driven by .spec.scaling (KEDA) instead.

Field Description Default Validation
apiVersion string agents.nanohype.dev/v1alpha1
kind string AgentFleet
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec AgentFleetSpec
status AgentFleetStatus

AgentFleetSpec

AgentFleetSpec composes kagent Agent / ModelConfig / ToolServer CRs plus platform-specific scaffolding (KEDA, NetworkPolicy, IRSA binding).

Appears in:

Field Description Default Validation
platformRef LocalRef
agents AgentSpec array Agents is the list of agents to provision in this fleet. MinItems: 1
scaling ScalingSpec Scaling controls KEDA's ScaledObject for the runtime Deployments. Optional: {}

AgentFleetStatus

AgentFleetStatus reports rollout state.

Appears in:

Field Description Default Validation
phase string Phase: Pending, Provisioning, Ready, ScaledToZero, Failed. Optional: {}
readyAgents integer ReadyAgents counts agents whose downstream Deployment is ready. Optional: {}
observedGeneration integer ObservedGeneration is the last spec.generation reconciled. Optional: {}
conditions Condition array Optional: {}

AgentSandbox

AgentSandbox is a Platform-scoped, single-use isolated pod for one agent role-session. It shares SandboxPool's hardening — Pod Security "restricted", default-deny networked, on the dedicated tainted node pool — but is push-dispatched (one session, run-once) rather than a pull-based pool of always-on workers.

Field Description Default Validation
apiVersion string agents.nanohype.dev/v1alpha1
kind string AgentSandbox
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec AgentSandboxSpec
status AgentSandboxStatus

AgentSandboxSpec

AgentSandboxSpec declares one ephemeral, hardened pod that runs a single agent role-session — fab's sdk role-loop dispatched per session. The reconciler builds the pod on the dedicated, tainted sandbox node pool, locked down by a default-deny NetworkPolicy, under the Platform's tenant IRSA ServiceAccount.

Appears in:

Field Description Default Validation
platformRef LocalRef PlatformRef is the owning Platform. The session pod runs in that
Platform's tenant namespace and the sandbox gates on Platform
readiness.
image string Image is the container image the session pod runs.
command string array Command overrides the image entrypoint. Optional: {}
args string array Args are the container arguments. Optional: {}
env EnvVar array Env is the session pod's environment. The dispatcher (fab) passes the
role, the role message, and any backend config through here.
Optional: {}
runtimeClassName string RuntimeClassName selects a Kubernetes RuntimeClass for the session
pod — "gvisor" or "kata" for kernel-level isolation of the untrusted
agent code. The named RuntimeClass must already exist. Empty uses the
cluster's default runtime.
Optional: {}
resources ResourceRequirements Resources are the session pod's resource requests and limits. Optional: {}
ttlSecondsAfterFinished integer TTLSecondsAfterFinished is how long the AgentSandbox is kept after its
session pod terminates before the operator garbage-collects it.
3600 Minimum: 0
Optional: {}

AgentSandboxStatus

AgentSandboxStatus reports the sandbox's reconciled state.

Appears in:

Field Description Default Validation
phase string Phase: Pending, Running, Succeeded, Failed, Suspended. Optional: {}
podName string PodName is the session pod's name in the tenant namespace. Optional: {}
podPhase string PodPhase mirrors the session pod's status.phase. Optional: {}
completedAt Time CompletedAt is when the session pod first reached a terminal phase —
the start of the TTL countdown.
Optional: {}
observedGeneration integer ObservedGeneration is the last spec.generation reconciled. Optional: {}
conditions Condition array Optional: {}

AgentSpec

AgentSpec is one agent in the fleet.

Appears in:

Field Description Default Validation
name string
systemPrompt string SystemPrompt is the agent's instruction text.
modelRoute string ModelRoute is the named route on the Platform's ModelGateway.
tools ToolRef array Tools is the list of kagent ToolServer references. Optional: {}
replicas integer Replicas overrides the fleet-wide scaling minimum for this agent. Optional: {}

BatchJob

BatchJob runs a single Amazon Bedrock batch-inference job for a Platform tenant.

Field Description Default Validation
apiVersion string agents.nanohype.dev/v1alpha1
kind string BatchJob
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec BatchJobSpec
status BatchJobStatus

BatchJobSpec

BatchJobSpec submits an Amazon Bedrock batch-inference job (CreateModelInvocationJob): an S3 JSONL of records in, an S3 JSONL of results out. One BatchJob maps to exactly one Bedrock job — there is no schedule; create a new CR for each run (the reconciler is idempotent on the spec, so re-applying the same CR never double-submits).

Appears in:

Field Description Default Validation
platformRef LocalRef
modelId string ModelID is the Bedrock model id or inference-profile id the batch job
invokes (e.g. "anthropic.claude-3-5-sonnet-20241022-v2:0" or a
cross-region "us.anthropic.…" profile). Validated server-side by
Bedrock; kept a free string here like Identity.AllowedModels.
MinLength: 1
modelInvocationType string ModelInvocationType selects the record schema in the input JSONL —
raw InvokeModel bodies or Converse turns.
InvokeModel Enum: [InvokeModel Converse]
inputS3Uri string InputS3Uri is the s3:// URI of the input JSONL (or its prefix). Pattern: ^s3://.+
outputS3Prefix string OutputS3Prefix is the s3:// prefix Bedrock writes results under. Pattern: ^s3://.+
timeoutHours integer TimeoutHours bounds the job's runtime. Bedrock requires 24..168. 24 Maximum: 168
Minimum: 24
serviceRoleArnOverride string ServiceRoleArnOverride replaces the operator-resolved Bedrock batch
service role (the role Bedrock assumes to read input / write output).
Normally empty — the reconciler injects the SSM-resolved role.
Optional: {}

BatchJobStatus

BatchJobStatus tracks the Bedrock job the reconciler submitted and polls.

Appears in:

Field Description Default Validation
jobArn string JobArn is the submitted job's ARN. Non-empty is the idempotency guard:
once set, the reconciler polls rather than re-submitting.
Optional: {}
jobName string JobName is the deterministic, Bedrock-sanitized job name. Optional: {}
phase string Phase: Pending, Provisioning, Running, Succeeded, Failed, Stopped. Optional: {}
submittedAt Time SubmittedAt / CompletedAt timestamps. Optional: {}
completedAt Time Optional: {}
outputLocation string OutputLocation is the s3:// URI Bedrock reports for the results. Optional: {}
recordCount integer RecordCount / SucceededCount / FailedCount mirror Bedrock's
ProcessedRecordCount / SuccessRecordCount / ErrorRecordCount once the
job is running or terminal.
Optional: {}
succeededCount integer Optional: {}
failedCount integer Optional: {}
message string Message carries the last Bedrock status / failure reason. Optional: {}
conditions Condition array Optional: {}

ModelGateway

ModelGateway is a per-Platform gateway CR that fronts Bedrock for one or more named routes.

Field Description Default Validation
apiVersion string agents.nanohype.dev/v1alpha1
kind string ModelGateway
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec ModelGatewaySpec
status ModelGatewayStatus

ModelGatewaySpec

ModelGatewaySpec configures a per-Platform gateway: the routes exposed, which Bedrock models back them, and which Guardrail attaches.

Appears in:

Field Description Default Validation
platformRef LocalRef PlatformRef is the owning Platform.
routes ModelRouteSpec array Routes is the list of named routes the gateway exposes. MinItems: 1
defaultGuardrailRef LocalRef DefaultGuardrailRef applies when a Route does not specify its own. Optional: {}

ModelGatewayStatus

ModelGatewayStatus surfaces the agentgateway Route/Listener state.

Appears in:

Field Description Default Validation
phase string Phase: Pending, Provisioning, Ready, Failed. Optional: {}
endpoint string Endpoint is the cluster-internal hostname of the gateway. Optional: {}
observedGeneration integer ObservedGeneration is the last spec.generation reconciled. Optional: {}
conditions Condition array Optional: {}

ModelRouteSpec

ModelRouteSpec is a single named route.

Appears in:

Field Description Default Validation
name string
modelFamily string ModelFamily: anthropic | meta | mistral | cohere | amazon-titan |
amazon-nova | stability.
Enum: [anthropic meta mistral cohere amazon-titan amazon-nova stability]
modelId string ModelId is the canonical Bedrock model ID or inference profile ID.
crossRegionProfile string CrossRegionProfile enables a Bedrock cross-region inference profile. Optional: {}
rateLimit integer RateLimit caps requests per minute (not tokens) on this route. The
operator renders it into an agentgateway local rate-limit policy with
unit=Minutes; 0 or unset disables rate limiting for the route.
Optional: {}
guardrailRef LocalRef GuardrailRef overrides the gateway's default guardrail. Optional: {}

SandboxPool

SandboxPool is a Platform-scoped pool of Managed Agents self-hosted sandbox workers. The reconciler runs them as a Deployment on the dedicated, tainted sandbox node pool, locked down by a default-deny NetworkPolicy.

Field Description Default Validation
apiVersion string agents.nanohype.dev/v1alpha1
kind string SandboxPool
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec SandboxPoolSpec
status SandboxPoolStatus

SandboxPoolSpec

SandboxPoolSpec declares a pool of Managed Agents self-hosted sandbox workers for a self_hosted environment. The workers run Anthropic's ant beta:worker, claiming sessions from the environment's work queue and executing agent tool calls inside the cluster.

Appears in:

Field Description Default Validation
platformRef LocalRef PlatformRef is the owning Platform. The pool's workers run in that
Platform's tenant namespace and the pool gates on Platform readiness.
environmentId string EnvironmentID is the Managed Agents self_hosted environment whose
work queue these workers drain (an env_... id).
environmentKeySecret SecretKeySelector EnvironmentKeySecret holds ANTHROPIC_ENVIRONMENT_KEY — the worker's
auth token, mounted into every worker pod.
apiKeySecret SecretKeySelector APIKeySecret holds the organization API key. It is consumed only by
the work-queue autoscaler, never mounted into worker pods — Anthropic
warns the org key must not be reachable by agent tool calls.
Optional: {}
image string Image overrides the sandbox worker image. Defaults to the platform's
published sandbox-worker image when empty.
Optional: {}
scaling SandboxScalingSpec Scaling bounds the worker count. Optional: {}
resources ResourceRequirements Resources are the per-worker-pod resource requests and limits. Optional: {}
runtimeClassName string RuntimeClassName selects a Kubernetes RuntimeClass for the worker
pods — typically "gvisor" or "kata" for kernel-level isolation of
the untrusted agent tool code. The named RuntimeClass must already
exist in the cluster. Empty uses the cluster's default runtime.
Optional: {}

SandboxPoolStatus

SandboxPoolStatus reports the pool's reconciled state.

Appears in:

Field Description Default Validation
phase string Phase: Pending, Ready, Suspended, Failed. Optional: {}
readyWorkers integer ReadyWorkers is the worker Deployment's ready replica count. Optional: {}
observedGeneration integer ObservedGeneration is the last spec.generation reconciled. Optional: {}
conditions Condition array Optional: {}

SandboxScalingSpec

SandboxScalingSpec bounds the worker Deployment's replica count.

Appears in:

Field Description Default Validation
minReplicas integer MinReplicas is the worker-count floor. A pointer so 0 (scale to zero,
for the autoscaled path) is distinguishable from "field absent".
1 Minimum: 0
Optional: {}
maxReplicas integer MaxReplicas is the worker-count ceiling for the autoscaler. 10 Minimum: 1
Optional: {}
queueDepthTarget integer QueueDepthTarget is the work-queue depth per worker the autoscaler
aims for before adding workers.
5 Minimum: 1
Optional: {}

ScalingSpec

ScalingSpec configures KEDA.

Appears in:

Field Description Default Validation
enabled boolean Enabled — when false, the operator scales the Deployment to 0 and
removes the ScaledObject. Toggled false by the kill-switch on budget
breach.
true
min integer Min replicas. Use a pointer so 0 (kill-switch state) is distinguishable
from "field absent" — with int32 + omitempty, the zero value gets
dropped and re-defaulted, making min=0 unrepresentable.
1 Minimum: 0
Optional: {}
max integer Max replicas. 10 Minimum: 1
Optional: {}
queueDepthTrigger integer QueueDepthTrigger: scale up when SQS depth exceeds this value. 10 Minimum: 1
Optional: {}
queueUrl string QueueUrl is the SQS queue the fleet's work originates from. When
set the operator emits a KEDA aws-sqs-queue trigger; otherwise a
CPU-utilization placeholder. The tenant IRSA role must have
sqs:GetQueueAttributes on this queue (granted via the agent-iam
baseline policy + an in-policy resource ARN derived from the URL).
Pattern: ^https://sqs\.[a-z0-9-]+\.amazonaws\.com/[0-9]\{12\}/[A-Za-z0-9_-]+(\.fifo)?$
Optional: {}

ToolRef

ToolRef references a kagent ToolServer by name.

Appears in:

Field Description Default Validation
name string

governance.nanohype.dev/v1alpha1

Package v1alpha1 contains API Schema definitions for the governance v1alpha1 API group.

Resource Types

BudgetPolicy

BudgetPolicy caps monthly spend per Platform and triggers the kill-switch at 120% of the threshold.

Field Description Default Validation
apiVersion string governance.nanohype.dev/v1alpha1
kind string BudgetPolicy
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec BudgetPolicySpec
status BudgetPolicyStatus

BudgetPolicySpec

BudgetPolicySpec sets monthly spend caps per Platform.

Appears in:

Field Description Default Validation
platformRef LocalRef
monthlyUsd string MonthlyUsd is the soft threshold expressed as a decimal-string USD amount
(e.g. "2500", "1500.50"). KillSwitch fires at 120% of this. Modeled as
string for symmetry with Status.CurrentSpendUsd and so future v1 can
support fractional cents without a lossy int32 → string conversion. The
pattern enforces non-negative decimal with optional 2-digit fraction.
MinLength: 1
Pattern: ^[0-9]+(\.[0-9]\{1,2\})?$
alertThresholdsPercent integer array AlertThresholdsPercent — fire WarnEvent at these % of the threshold. [50 80 100] Optional: {}
killSwitchEnabled boolean KillSwitchEnabled — when false, breach at 120% is logged but not acted on.
Use sparingly; SOC2 platforms must keep this true.
true

BudgetPolicyStatus

BudgetPolicyStatus surfaces the latest spend reading. The budget reconciler updates this on every tick (hourly in prod, 5m in dev) with current spend, percent-of-budget, the alert thresholds crossed, and reconcile conditions.

Appears in:

Field Description Default Validation
currentSpendUsd string CurrentSpendUsd is the most recent spend snapshot. Optional: {}
percentOfBudget integer PercentOfBudget — 0..200+. Optional: {}
lastReconciled Time LastReconciled timestamp. Optional: {}
killSwitchFiredAt Time KillSwitchFiredAt — non-null once the kill-switch has published a
breach event. Firing is not the same as taking effect: the platform is
suspended by an out-of-band EventBridge→StepFunctions path, and the
reconciler confirms the effect (platform observed Suspended) before it
treats the switch as done. See KillSwitchRefireCount and the
KillSwitchUnrouted condition.
Optional: {}
killSwitchRefireCount integer KillSwitchRefireCount is how many times the breach event has been
re-published because the platform was not observed Suspended within the
grace window. Bounded — after the cap the reconciler stops re-publishing
but keeps the KillSwitchUnrouted condition set so the alert stays lit.
Optional: {}
killSwitchLastRefireAt Time KillSwitchLastRefireAt is the timestamp of the most recent re-publish.
It anchors the exponential backoff between re-fires.
Optional: {}
conditions Condition array Optional: {}

EvalCase

EvalCase is a single test case. The assertion fields it sets determine its kind — the runner has no separate discriminator:

  • Golden case: sets ExpectContains (and optionally MaxLatencyMs / MaxCostUsd). Passes when the agent's output contains every listed substring and stays within the latency/cost ceilings.
  • Adversarial / injection case: sets ExpectNotContains and/or ExpectRefusal. Passes when the output leaks none of the forbidden substrings and — when ExpectRefusal is set — the agent declined (a guardrail intervened, or the output matched a refusal).

A case may combine both families (e.g. a jailbreak attempt that must be refused AND must not echo a secret). All assertions present must hold.

Appears in:

Field Description Default Validation
name string
input string
expectContains string array ExpectContains: the output must contain every one of these substrings
(golden / positive assertion). Empty = no positive-content assertion.
Optional: {}
expectNotContains string array ExpectNotContains: the output must contain none of these substrings
(adversarial / data-leak assertion — e.g. a secret, PII, or a phrase
that would indicate the agent complied with an injection). Empty = no
forbidden-content assertion.
Optional: {}
expectRefusal boolean ExpectRefusal: when true, the case passes only if the agent declined —
either the model gateway reported a guardrail intervention, or the
output matched a refusal. Use for adversarial prompts that should be
blocked rather than answered.
Optional: {}
maxLatencyMs integer MaxLatencyMs: if set (>0), the case fails when the observed round-trip
latency exceeds this ceiling.
Optional: {}
maxCostUsd string MaxCostUsd: if set, the case fails when the observed per-call cost
exceeds this ceiling. A model with no pricing entry (unpriced) fails
this assertion closed rather than passing on a misleading $0.
Optional: {}

EvalSuite

EvalSuite is a scheduled evaluation run against an AgentFleet's agents.

Field Description Default Validation
apiVersion string governance.nanohype.dev/v1alpha1
kind string EvalSuite
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec EvalSuiteSpec
status EvalSuiteStatus

EvalSuiteSpec

EvalSuiteSpec defines a periodic evaluation run against an AgentFleet.

Appears in:

Field Description Default Validation
platformRef LocalRef
agentFleetRef LocalRef AgentFleetRef targets the fleet whose agents are under test.
schedule string Schedule (cron) — when to run the suite. Empty = manual only. Optional: {}
cases EvalCase array Cases is the list of test cases (input prompt + expected criteria).
In production these are typically loaded from an S3 manifest; this
inline list is for small / dev suites.
Optional: {}
casesFromManifest string CasesFromManifest loads from eval-reports/<platform>/manifests/<name>.json
in the eval-reports S3 bucket.
Optional: {}
passThreshold string PassThreshold (0..1) is the required mean score for the run to be
marked passing. Argo Rollouts AnalysisTemplate consumes this signal.
Modeled as a string so reviewers see decimals in kubectl get -o yaml
without int<->float coercion surprises; pattern enforces 0.0 .. 1.0.
0.85 Pattern: ^(0(\.[0-9]+)?|1(\.0+)?)$

EvalSuiteStatus

EvalSuiteStatus reports the latest run.

Appears in:

Field Description Default Validation
lastRunAt Time LastRunAt timestamp. Optional: {}
lastScore string LastScore (mean across cases, 0..1). Optional: {}
lastReportUrl string LastReportURL (s3:// URL to the rendered HTML report). Optional: {}
phase string Phase: Pending, Running, Passed, Failed. Optional: {}
conditions Condition array Optional: {}

platform.nanohype.dev/v1alpha1

Package v1alpha1 contains API Schema definitions for the platform v1alpha1 API group.

Resource Types

AttributionSpec

AttributionSpec configures per-session human attribution for a Platform. See github.com/nanohype/fab docs/attribution.md for the consumer side.

Appears in:

Field Description Default Validation
operators string array Operators is the set of human identities (e.g. email addresses) a
session in this Platform may act as. Each value becomes both an allowed
STS SourceIdentity on the session role's trust policy and a resourceNames
entry on the impersonate ClusterRole, so the SAME string binds the AWS
and Kubernetes audit records. Use a canonical form (a lowercased email);
it must byte-match the operator's own RBAC subject name.
MinItems: 1
sessionRoleMaxDurationSeconds integer SessionRoleMaxDurationSeconds caps the assumed session lifetime. Because
the caller is the tenant IRSA role, AWS STS role chaining hard-caps a
chained session at 3600s regardless of this value; larger values only
matter if the caller ever changes. Defaults to 3600.
3600 Maximum: 43200
Minimum: 900
Optional: {}

BudgetRef

BudgetRef points at a BudgetPolicy by name.

Appears in:

Field Description Default Validation
name string

ComplianceSpec

ComplianceSpec enables stricter defaults.

Appears in:

Field Description Default Validation
hipaa boolean HIPAA: object-lock compliance mode, no cross-region inference, PII detect
required on Guardrails.
Optional: {}
soc2 boolean SOC2: invocation logging required, kill-switch enabled. Optional: {}

ContactSpec

ContactSpec carries owner / on-call / billing reach paths.

Appears in:

Field Description Default Validation
slackChannel string SlackChannel for tenant-wide notifications (e.g. "#acme-ops"). Optional: {}
oncallRotation string OncallRotation — Pagerduty schedule key or similar identifier. Optional: {}
billingEmail string BillingEmail — invoice + budget-breach notification recipient. Optional: {}

IdentitySpec

IdentitySpec wires the per-Platform IRSA role. The controller reconciles a bedrock-model-scoping inline policy onto the tenant role (and the attribution session role, when spec.attribution is set) that denies the Bedrock model-invoke actions (InvokeModel, InvokeModelWithResponseStream, Converse, ConverseStream) on every resource outside the set that AllowedModels / AllowedModelFamilies expand to. The baseline policy's broad invoke grant is thereby narrowed to exactly the declared models; when neither field is set the policy denies all model invocation (deny-by-default).

Appears in:

Field Description Default Validation
allowedModels string array AllowedModels is the list of Bedrock model IDs or cross-region
inference-profile IDs (e.g. "anthropic.claude-sonnet-4-6",
"us.anthropic.claude-sonnet-4-6-v1:0") the role may invoke. The
controller expands each entry into its foundation-model ARN pattern plus
the matching inference-profile ARN pattern (a us. profile fans out to
foundation models across regions, so both are granted together) and
reconciles them into the role's bedrock-model-scoping policy. Scopes
tighter than a family; mutually exclusive with AllowedModelFamilies.
Optional: {}
allowedModelFamilies string array AllowedModelFamilies (e.g. ["anthropic", "amazon-nova"]) is expanded by
the controller at reconcile time into the family's foundation-model ARN
pattern (arn::bedrock:::foundation-model/) and, for
families with cross-region inference profiles (anthropic, amazon-nova,
meta, mistral), the us. inference-profile ARN pattern
(arn::bedrock:::inference-profile/us.*),
then reconciled into the role's bedrock-model-scoping policy. Leaving
both this and AllowedModels empty denies all Bedrock model invocation
for the Platform's roles.
items:Enum: [anthropic amazon-nova amazon-titan meta mistral cohere stability]
Optional: {}
extraPolicyArns string array ExtraPolicyArns are managed IAM policies attached on top of the baseline. Optional: {}

Platform

Platform is the top-level tenancy CR. Namespaced so that BudgetPolicy, ModelGateway, AgentFleet, and EvalSuite references resolve in the same namespace by name. The operator provisions the tenant workload namespace (tenants-) separately at reconcile time; the Platform CR itself lives in whichever namespace the cluster admin places it (typically a management namespace such as eks-agent-platform).

Field Description Default Validation
apiVersion string platform.nanohype.dev/v1alpha1
kind string Platform
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec PlatformSpec
status PlatformStatus

PlatformSpec

PlatformSpec defines the desired state of a Platform — a tenancy boundary hosting one or more AgentFleets, with its own budget, identity, and guardrails.

Appears in:

Field Description Default Validation
displayName string DisplayName is a human-readable name for dashboards and CLI output. Optional: {}
persona string Persona drives default values for AgentFleet, ModelGateway, and
dashboards. One of: sales-ops, support, finance, ops, founder, eng,
marketing, legal, generic.
generic Enum: [sales-ops support finance ops founder eng marketing legal generic]
tenant string Tenant is the owning Tenant CR (one Tenant can own multiple Platforms).
budget BudgetRef Budget references a BudgetPolicy CR in the same namespace.
identity IdentitySpec Identity controls how the IRSA role is named + which Bedrock models are
reachable.
compliance ComplianceSpec Compliance flags drive stricter defaults across the Platform. Optional: {}
isolation string Isolation is the workload-isolation tier:
- namespace (default): namespace RBAC + default-deny NetworkPolicy +
ResourceQuota + PSS-restricted, tenant workloads on the host API server.
- vcluster: the same host-side containment PLUS a per-Platform virtual
cluster, so tenant code that talks to the Kubernetes API talks to its own
API server, not the host's (API-server-level isolation — NOT kernel/node
isolation; see docs/adr/0009-vcluster-isolation-tier.md and SECURITY.md).
Immutable: switching tiers on a live Platform is a migration (it would strand
the virtual cluster and its synced host objects), so the tier is fixed at
create time. Re-declare the Platform to change it. Enforced at admission by
the CEL transition rule below — an invalid tier flip fails the apply rather
than silently half-reconciling.
namespace Enum: [namespace vcluster]
Optional: {}
attribution AttributionSpec Attribution opts the Platform into per-session human attribution. When
set, the operator provisions a session role — assumable by the tenant
IRSA role with the operator carried as STS SourceIdentity, scoped to the
tenant baseline (Bedrock invoke) and NOT broad sts:AssumeRole — plus a
ClusterRole letting the tenant ServiceAccount impersonate the named
operators at the apiserver. fab's role-session entrypoint consumes both,
so an agent's AWS + Kubernetes actions attribute to a named human.
nil = unattributed (the default).
Optional: {}

PlatformStatus

PlatformStatus captures the controller's view of the world.

Appears in:

Field Description Default Validation
phase string Phase: Pending, Provisioning, Ready, Suspended, Failed. Optional: {}
iamRoleArn string IamRoleArn is the per-Platform IRSA role created by the controller. Optional: {}
sessionRoleArn string SessionRoleArn is the per-Platform attribution session role, created when
spec.attribution is set. Empty when attribution is off.
Optional: {}
namespace string Namespace is the tenant namespace the controller provisioned. Optional: {}
observedGeneration integer ObservedGeneration is the last spec.generation the controller reconciled. Optional: {}
suspendedAt Time SuspendedAt is the timestamp at which the kill-switch fired. When
non-nil the operator stops reattaching the baseline IAM policy and
the AgentFleetReconciler scales fleets to zero. Resets to nil only
when ops clears the iam:TagRole 'platform.nanohype.dev/suspended'
marker on the tenant IRSA role.
Optional: {}
suspendedReason string SuspendedReason carries the kill-switch's reason (e.g.
'budget-exceeded'). Same lifecycle as SuspendedAt.
Optional: {}
conditions Condition array Conditions follows the standard kubernetes pattern. Optional: {}

Tenant

Tenant is the cluster-scoped organizational owner of one or more Platforms. Provides aggregate budget / readiness / suspension views and a single point for non-technical persona dashboards to land on.

Field Description Default Validation
apiVersion string platform.nanohype.dev/v1alpha1
kind string Tenant
metadata ObjectMeta Refer to Kubernetes API documentation for fields of metadata.
spec TenantSpec
status TenantStatus

TenantSpec

TenantSpec describes an organization (or sub-org) that owns one or more Platforms. Tenant is cluster-scoped — it doesn't represent a Kubernetes namespace; it represents an organizational boundary that crosses Platforms. The relationship to Platform is by Platform.spec.tenant referencing Tenant.metadata.name.

Appears in:

Field Description Default Validation
displayName string DisplayName is the human-readable tenant name shown in dashboards
and persona UX.
Optional: {}
primaryPersona string PrimaryPersona drives default values for new Platforms onboarded
into this tenant. One of the standard persona names.
generic Enum: [sales-ops support finance ops founder eng marketing legal generic]
contact ContactSpec Contact carries human-readable owner info (Slack channel, on-call
rotation, billing email) for ops to reach.
Optional: {}
compliance ComplianceSpec Compliance baseline applied to every Platform owned by this Tenant
unless the Platform itself sets a stricter value.
Optional: {}
aggregateMonthlyBudgetUsd string AggregateMonthlyBudgetUsd is the soft cap on the SUM of all owned
Platforms' BudgetPolicy.spec.monthlyUsd. Status reports whether the
sum exceeds this; the operator does not enforce — each Platform's
own BudgetPolicy is the enforcement layer. Modeled as a decimal-
string to mirror BudgetPolicy.monthlyUsd.
Pattern: ^[0-9]+(\.[0-9]\{1,2\})?$
Optional: {}

TenantStatus

TenantStatus aggregates the state of Platforms owned by this Tenant.

Appears in:

Field Description Default Validation
phase string Phase: Pending, Active, Suspended (any owned Platform suspended),
Failed.
Optional: {}
platformCount integer PlatformCount is the number of Platform CRs whose
spec.tenant == Tenant.metadata.name.
Optional: {}
readyPlatformCount integer ReadyPlatformCount is the subset of PlatformCount in phase=Ready. Optional: {}
suspendedPlatformCount integer SuspendedPlatformCount is the subset in phase=Suspended. Optional: {}
aggregateSpendUsd string AggregateSpendUsd is the sum of CurrentSpendUsd across all owned
BudgetPolicies (one per owned Platform).
Optional: {}
aggregateBudgetUsd string AggregateBudgetUsd is the sum of MonthlyUsd across all owned
BudgetPolicies.
Optional: {}
percentOfBudget integer PercentOfBudget — 0..200+. Computed from AggregateSpend /
AggregateBudget. When > 100 a TenantBudgetExceeded condition fires.
Optional: {}
lastReconciled Time LastReconciled timestamp. Optional: {}
conditions Condition array Optional: {}