Kubernetes API Reference
This document provides the working reference for the TinySystems Custom Resource Definitions (CRDs) you interact with most: TinyNode and TinyModule. For the full generated CRD reference (including TinyFlow, TinyProject, TinyScenario and TinyWidgetPage) see the generated API docs.
Source of truth: api/v1alpha1/tinynode_types.go, api/v1alpha1/tinymodule_types.go in the SDK (github.com/tiny-systems/module).
TinyNode
Represents an instance of a component in a flow.
apiVersion/kind
apiVersion: operator.tinysystems.io/v1alpha1
kind: TinyNode
Spec
spec:
module: string # Module name - container image repo + tag (required)
component: string # Component name within the module (required)
ports: # Port configurations (data mapping lives here)
- from: string # Sender's full port name (config depends on sender)
port: string # This node's port name (required)
schema: <bytes> # JSON schema of the port (base64-encoded bytes)
configuration: <bytes># JSON data of the port's configuration (base64-encoded bytes)
flowID: string
edges: # Outgoing connections
- id: string # Edge id (required)
port: string # This node's source port name (required)
to: string # Other node's full port name, "node:port" (required)
flowID: string # (required)
retryPolicy: # Optional per-edge retry policy
maxAttempts: int # 1-10; 1 = no retry (default)
initialDelayMs: int # Initial backoff, default 1s
backoffCoefficient: string # Multiplier per attempt, default "2.0"
maxDelayMs: int # Cap on a single attempt's delay, default 30s
nonRetryableErrorCodes: [string] # Error codes that skip retry
timeoutMs: int # Per-attempt handler timeout; 0 = transport default
Note: edge data mapping is not stored on the edge. The receiving node stores it in spec.ports[] as a TinyNodePortConfig whose from field names the sending node's port.
Status
status:
observedGeneration: int64 # Most recent generation observed by the controller
module: # Resolved module
name: string
version: string
sdkVersion: string # SDK version the module was built with
component: # Component metadata
description: string
info: string
tags: [string]
ports: # Port definitions published by the component
- name: string
label: string
position: int # 0=Top, 1=Right, 2=Bottom, 3=Left
source: boolean # true = output port
schema: <bytes> # JSON Schema (base64-encoded bytes)
configuration: <bytes># Current configuration (base64-encoded bytes)
status: string # Free-form status message
metadata: {} # map[string]string — component state propagation
error: boolean # true when the node is in error
lastUpdateTime: string # RFC3339 timestamp
Example
apiVersion: operator.tinysystems.io/v1alpha1
kind: TinyNode
metadata:
name: myproject.common.router-abc12
namespace: tinysystems
labels:
tinysystems.io/flow-name: "flow-123"
tinysystems.io/project-name: "myproject"
tinysystems.io/module-version-major: "common-v1"
spec:
module: ghcr.io/tiny-systems/common-module:v1.5.0
component: router
edges:
- id: "edge-1"
port: "out_success"
to: "myproject.common.process-def34:input"
flowID: "flow-123"
- id: "edge-2"
port: "out_default"
to: "myproject.common.errorhandler-ghi56:input"
flowID: "flow-123"
retryPolicy:
maxAttempts: 3
initialDelayMs: 1000
backoffCoefficient: "2.0"
TinyModule
Represents a deployed module in the cluster.
apiVersion/kind
apiVersion: operator.tinysystems.io/v1alpha1
kind: TinyModule
Spec
spec:
image: string # Container image
Status
status:
addr: string # Listen address of the module server
name: string # Module name
version: string # Module version
sdkVersion: string # SDK version the module was built with
components: # Available components
- name: string
description: string
info: string
tags: [string]
ports: # Component-level port metadata (pre-install discovery)
- name: string
label: string
source: boolean # true = output port
position: int # 0=Top, 1=Right, 2=Bottom, 3=Left
schema: <bytes> # JSON schema (base64-encoded bytes)
Example
apiVersion: operator.tinysystems.io/v1alpha1
kind: TinyModule
metadata:
name: common-module-v1
namespace: tinysystems
spec:
image: ghcr.io/tiny-systems/common-module:v1.5.0
status:
addr: ":50051"
name: ghcr.io/tiny-systems/common-module
version: "1.5.0"
sdkVersion: "0.13.59"
components:
- name: router
description: "Route messages based on conditions"
info: "Evaluates conditions and routes to the matching output port."
tags: ["routing", "control-flow"]
External Triggers
There is no TinySignal CRD. External systems trigger node ports by publishing directly to the runtime over NATS via the SDK's wire package:
import "github.com/tiny-systems/module/pkg/wire"
// Send data to a node's port; returns the node's synchronous reply.
reply, err := wire.Publish(ctx, nc, targetNode, port, data, wire.Options{})
The platform's tooling (MCP send_signal, dashboards, schedulers) uses this path.
Field Reference Tables
TinyNode.spec
| Field | Type | Required | Description |
|---|---|---|---|
| module | string | Yes | Module name — container image repo + tag |
| component | string | Yes | Component name within the module |
| ports | TinyNodePortConfig | No | Port configurations (data mapping) |
| edges | TinyNodeEdge | No | Outgoing connections |
TinyNode.spec.edges (TinyNodeEdge)
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Edge id |
| port | string | Yes | This node's source port name |
| to | string | Yes | Other node's full port name (node:port) |
| flowID | string | Yes | Flow the edge belongs to |
| retryPolicy | EdgeRetryPolicy | No | Per-edge retry policy |
EdgeRetryPolicy
| Field | Type | Default | Description |
|---|---|---|---|
| maxAttempts | int | 1 | Max total dispatch attempts (1-10); 1 = no retry |
| initialDelayMs | int | 1000 | Initial backoff between attempts |
| backoffCoefficient | string | "2.0" | Multiplier applied to the delay each attempt |
| maxDelayMs | int | 30000 | Cap on a single attempt's delay |
| nonRetryableErrorCodes | string | — | Codes (from pkg/errors.NonRetryable) that skip retry, e.g. quota_exceeded, unauthorized, content_filter, validation |
| timeoutMs | int | 0 | Per-attempt handler timeout; 0 = transport default (5 min for NATS transports) |
Only failures a component marked transient (module.Retryable) are re-dispatched; unmarked errors surface immediately regardless of maxAttempts.
TinyNode.spec.ports (TinyNodePortConfig)
| Field | Type | Required | Description |
|---|---|---|---|
| from | string | No | Sender's full port name (settings depend on a sender) |
| port | string | Yes | This node's port name |
| schema | bytes | No | JSON schema of the port |
| configuration | bytes | No | JSON data of the port's configuration |
| flowID | string | No | Flow the configuration belongs to |
TinyNode.status
| Field | Type | Description |
|---|---|---|
| observedGeneration | int64 | Most recent generation observed by the controller |
| module | TinyNodeModuleStatus | {name, version, sdkVersion} |
| component | TinyNodeComponentStatus | {description, info, tags} |
| ports | TinyNodePortStatus | {name, label, position (int 0-3), source, schema, configuration} |
| status | string | Free-form status message |
| metadata | mapstringstring | Component state propagation |
| error | boolean | True when the node is in error |
| lastUpdateTime | Time | Last status update |
TinyModule.spec
| Field | Type | Required | Description |
|---|---|---|---|
| image | string | Yes | Container image reference |
TinyModule.status
| Field | Type | Description |
|---|---|---|
| addr | string | Listen address of the module server |
| name | string | Module name |
| version | string | Module version |
| sdkVersion | string | SDK version the module was built with |
| components | TinyModuleComponentStatus | {name, description, info, tags, ports} |
Labels and Annotations
All keys use the tinysystems.io/ prefix (constants in api/v1alpha1/tinynode_types.go).
Labels
| Label | Constant | Description |
|---|---|---|
tinysystems.io/flow-name | FlowNameLabel | Flow the node belongs to |
tinysystems.io/project-name | ProjectNameLabel | Project the resource belongs to |
tinysystems.io/node-name | NodeNameLabel | Node name (attaching related resources to nodes) |
tinysystems.io/module-version-major | ModuleNameMajorLabel | Module major version |
tinysystems.io/dashboard | DashboardLabel | Dashboard association |
tinysystems.io/execution-mode | ExecutionModeLabel | durable = async ack-on-emit execution surviving pod death |
Annotations
| Annotation | Constant | Description |
|---|---|---|
tinysystems.io/page-name | PageTitleAnnotation | Widget page title |
tinysystems.io/page-sort-idx | PageSortIdxAnnotation | Widget page sort index |
tinysystems.io/project-name | ProjectNameAnnotation | Project name |
tinysystems.io/flow-description | FlowDescriptionAnnotation | Flow description |
tinysystems.io/node-handles | NodeHandlesAnnotation | Node handles |
tinysystems.io/shared-with-flows | SharedWithFlowsAnnotation | Flows a shared node is visible in |
tinysystems.io/component-pos-x | ComponentPosXAnnotation | Editor X coordinate |
tinysystems.io/component-pos-y | ComponentPosYAnnotation | Editor Y coordinate |
tinysystems.io/component-pos-spin | ComponentPosSpinAnnotation | Editor rotation |
tinysystems.io/node-label | NodeLabelAnnotation | User-facing node label |
tinysystems.io/node-comment | NodeCommentAnnotation | User comment on the node |
tinysystems.io/ingress-hostname-suffix | IngressHostNameSuffixAnnotation | Suffix for auto-generated ingress hostnames |
tinysystems.io/scenario-name | ScenarioNameAnnotation | Scenario association |
RBAC Requirements
Minimum Permissions
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: tinysystems-controller
rules:
- apiGroups: ["operator.tinysystems.io"]
resources: ["tinynodes", "tinymodules", "tinyflows", "tinyprojects", "tinyscenarios", "tinywidgetpages"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["operator.tinysystems.io"]
resources: ["tinynodes/status", "tinymodules/status"]
verbs: ["get", "update", "patch"]