> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kombify.io/llms.txt
> Use this file to discover all available pages before exploring further.

# List canonical Node runtime state

> Returns owner-scoped Nodes with canonical `node_id` and
`kit_deployment_id` identities.




## OpenAPI

````yaml /techstack/reference/api/openapi.yaml get /api/v1/servers
openapi: 3.1.0
info:
  title: kombify-TechStack API
  description: >
    REST API for kombify-TechStack -- the hybrid cloud control plane for
    homelabs.


    kombify-TechStack manages infrastructure through a spec-driven architecture:

    validate YAML specs via CUE, generate OpenTofu configurations, and manage

    nodes through a gRPC agent protocol.


    ## Authentication


    Authenticated endpoints accept an OIDC/JWKS bearer token or an API key

    where documented. Self-hosted TechStack defaults to Pocket ID as identity

    provider. SaaS routes enter through the edge with Auth0 as the platform

    identity provider. PocketBase session exchange remains legacy migration

    compatibility only.


    ## Response Format


    **Success:** `{ "data": <object>, "meta": { "total": int, "page": int,
    "per_page": int } }`


    **Error:** `{ "error": { "code": "<ERROR_CODE>", "message": "...",
    "details": <any> } }`


    ## Pagination


    List endpoints accept `page` (default: 1) and `per_page` (default: 20, max:
    100) query parameters.
  version: 1.0.0
  contact:
    name: kombify
    url: https://kombify.io
  license:
    name: Apache-2.0 AND GPL-3.0
    url: https://github.com/KombiverseLabs/kombify-TechStack/blob/main/LICENSE
servers:
  - url: https://api.kombify.io/v1/techstack
    description: >-
      Production canonical (via Cloudflare edge gateway, strip-prefix). Clients
      MUST use this projection. The Gateway strips /v1/techstack and re-adds
      /api/v1 at the origin, so it resolves the /api/v1/* paths below cleanly.
  - url: http://localhost:5260
    description: Local development
  - url: https://techstack.kombify.io
    description: Production (direct, no Gateway prefix)
  - url: https://api.kombify.io/v1/orchestrator
    description: >-
      Legacy StackKit-Orchestrator projection of the same origin. RETAINED for
      backward compatibility with existing consumers only. Do NOT use for mobile
      or new clients: combined with the /api/v1/* paths it double-resolves
      (yielding /v1/orchestrator/api/v1/...). Prefer /v1/techstack.
security:
  - bearerAuth: []
tags:
  - name: Health
    description: Health checks and service info (no auth required)
  - name: Instance
    description: Local instance identity and enrollment metadata
  - name: Stacks
    description: Stack lifecycle management (create, provision, deploy, destroy)
  - name: Stacks - Specs
    description: Access persisted specification chain (intent, requirements, unified)
  - name: Stacks - Import/Export
    description: Import and export StackKits stack-spec.yaml configurations
  - name: Stacks - Drift
    description: Infrastructure drift detection and resolution
  - name: Unifier
    description: Spec validation, analysis, unification, and IaC generation pipeline
  - name: StackKits
    description: Infrastructure template catalog
  - name: Add-ons
    description: Add-on detection and registry
  - name: Workers
    description: Worker node registration and management
  - name: Servers
    description: Canonical server lifecycle, connection, and health state
  - name: Inventory
    description: >-
      Owner-scoped sanitized server and service read models for UI, API, and MCP
      clients
  - name: Pre-Checks
    description: Pre-deployment hardware and software validation
  - name: Agents
    description: Connected gRPC agent management and commands
  - name: Jobs
    description: Background job monitoring and SSE streaming
  - name: Discovery
    description: Network device discovery and SSH testing
  - name: Features
    description: Feature flags (read-only; managed centrally via the kombify Admin API)
  - name: Monthly Runtime
    description: Provider-free user API for subscription-backed stack runtime control
  - name: Runtime
    description: Recent runtime/deploy logs (job/deploy progress + container tail)
  - name: Wallet
    description: >-
      Redacted recovery-item wallet with biometric/platform-reauth-gated reveal.
      List responses strip secret/totp; reveal requires a fresh trusted-reauth
      HMAC proof (5-minute window) and is audited server-side.
  - name: Trust
    description: Pairing tokens for worker enrollment
  - name: Client Binding
    description: >-
      Short-lived HTTPS pairing for a second client and normal OIDC account
      handoff
  - name: Tunnel
    description: Cloudflare tunnel management for NAT traversal
  - name: Backups
    description: Database backup management (admin only)
  - name: Auth
    description: Authentication mode and SSO configuration
  - name: Metrics
    description: Prometheus-compatible instance metrics for admin/infra scrapers
  - name: Internal
    description: >-
      Internal SaaS-only APIs, including servicecall-protected executor
      contracts
paths:
  /api/v1/servers:
    get:
      tags:
        - Servers
      summary: List canonical Node runtime state
      description: |
        Returns owner-scoped Nodes with canonical `node_id` and
        `kit_deployment_id` identities.
      operationId: listServerRuntimes
      parameters:
        - name: kit_deployment_id
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Owner-scoped server runtime list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServerRuntime'
                  meta:
                    $ref: '#/components/schemas/ResponseMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    ServerRuntime:
      type: object
      required:
        - id
        - node_id
        - name
        - lifecycle
        - connection
        - health
        - channels
        - inventory_revision
        - provider
        - mutations_allowed
        - allowed_actions
        - stack_actions
        - created_at
        - updated_at
      properties:
        id:
          type: string
          description: Compatibility alias for node_id.
        node_id:
          type: string
        kit_deployment_id:
          type: string
        worker_id:
          type: string
        name:
          type: string
        lifecycle:
          type: object
          required:
            - state
            - desired_state
          properties:
            state:
              type: string
              enum:
                - planned
                - provisioning
                - enrolling
                - active
                - failed
                - decommissioning
                - decommissioned
            desired_state:
              type: string
              enum:
                - running
                - stopped
                - absent
            ended_at:
              type: string
              format: date-time
        connection:
          type: object
          required:
            - state
            - changed_at
          properties:
            state:
              type: string
              enum:
                - pending
                - connecting
                - connected
                - degraded
                - stale
                - offline
                - revoked
            reason_code:
              type: string
            changed_at:
              type: string
              format: date-time
            last_heartbeat_at:
              type: string
              format: date-time
            staleness_seconds:
              type: integer
              format: int64
              minimum: 0
        health:
          type: object
          required:
            - state
          properties:
            state:
              type: string
              enum:
                - unknown
                - healthy
                - degraded
                - unhealthy
            observed_at:
              type: string
              format: date-time
        channels:
          type: array
          items:
            $ref: '#/components/schemas/ServerChannel'
        inventory_revision:
          type: integer
          format: int64
          minimum: 0
        provider:
          type: object
          properties:
            lease_id:
              type: string
            ref:
              type: string
        environment_class:
          type: string
          enum:
            - local
            - cloud
            - unknown
        offering:
          type: string
          enum:
            - self_owned_device
            - external_vps
            - managed_vps
        provider_id:
          type: string
        provider_target_ref:
          type: string
        availability_owner:
          type: string
          enum:
            - customer
            - provider
        operations_owner:
          type: string
          enum:
            - customer
            - kombify
        target_evidence:
          type: object
          required:
            - freshness
          properties:
            ref:
              type: string
            observed_at:
              type: string
              format: date-time
            freshness:
              type: object
              required:
                - state
              properties:
                state:
                  type: string
                  enum:
                    - recorded
                    - unknown
                age_seconds:
                  type: integer
                  format: int64
                  minimum: 0
        mutations_allowed:
          type: boolean
          description: Coarse legacy gate. `allowed_actions` is the precise contract.
        allowed_actions:
          type: array
          uniqueItems: true
          description: >-
            Node-scoped operations this server's own state admits. Each id maps
            to exactly one endpoint that exists; an unknown lifecycle advertises
            nothing rather than guessing that a mutation is safe. The
            lease-scoped ids target `provider.lease_id`. There is deliberately
            no node `logs` id - no such endpoint exists.
          items:
            type: string
            enum:
              - connect
              - terminal
              - reconnect
              - rotate_credentials
              - ssh_enable
              - ssh_disable
              - detach
              - decommission
              - resolve_custody
              - reboot
              - os_update_plan
              - os_update
        stack_actions:
          type: array
          uniqueItems: true
          description: >-
            StackKit-deployment operations, all routed to POST
            /api/v1/stacks/{id}/stackkit/operations. Kept separate from
            `allowed_actions`: a node operation and a kit operation have
            different blast radius and different authority.
          items:
            type: string
            enum:
              - plan
              - apply
              - verify
              - upgrade
              - drift_detect
              - drift_reconcile
        reach:
          $ref: '#/components/schemas/GuardReach'
        security:
          $ref: '#/components/schemas/ServerSecurity'
        recovery:
          $ref: '#/components/schemas/ServerRecovery'
        updates:
          $ref: '#/components/schemas/ServerUpdates'
        capabilities:
          $ref: '#/components/schemas/ServerCapabilities'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    ResponseMeta:
      type: object
      properties:
        total:
          type: integer
        page:
          type: integer
        per_page:
          type: integer
        managed_runtime_inventory_complete:
          type: boolean
          description: >-
            True only when the managed RuntimeLease authority was configured and
            read successfully for this inventory response.
        worker_inventory_sha256:
          type: string
          pattern: ^[0-9a-f]{64}$
          description: >-
            Stable digest of the complete worker identity, attachment,
            freshness, and managed RuntimeLease authority snapshot used for
            pagination.
        managed_runtime_active_lease_ids:
          type: array
          items:
            type: string
          description: >-
            Canonically sorted IDs of visible managed RuntimeLeases classified
            as active for inventory and cleanup. This visibility projection is
            not capacity reservation or release authority.
        managed_runtime_inactive_lease_ids:
          type: array
          items:
            type: string
          description: >-
            Canonically sorted IDs of visible managed RuntimeLeases classified
            as cancelled or archived for inventory and cleanup. Inactive state
            does not prove provider absence or release managed-server capacity.
        managed_runtime_lease_generation_digests:
          type: array
          items:
            type: object
            required:
              - lease_id
              - resource_generation_digest
            properties:
              lease_id:
                type: string
              resource_generation_digest:
                type: string
                pattern: ^[0-9a-f]{64}$
          description: >-
            Canonically sorted opaque bindings from each visible managed
            RuntimeLease ID to its exact provider-resource generation. Missing
            coverage makes destructive inventory proof invalid while leaving
            ordinary dashboard inventory readable.
        managed_runtime_duplicate_lease_ids:
          type: array
          items:
            type: string
          description: >-
            Managed RuntimeLease IDs represented by multiple persisted worker
            rows before UI projection deduplication; must be empty for
            destructive inventory proof.
        managed_runtime_attachment_conflict_lease_ids:
          type: array
          items:
            type: string
          description: >-
            Canonically sorted caller-visible managed RuntimeLease IDs with a
            conflicting tenant-wide worker attachment; must be empty for
            destructive inventory proof and never exposes foreign private lease
            or worker details.
    ServerChannel:
      type: object
      required:
        - type
        - role
        - state
      properties:
        type:
          type: string
          enum:
            - grpc-mtls
            - ssh
            - cloudflare-tunnel
            - provider-api
        role:
          type: string
          enum:
            - primary
            - fallback
            - info-only
        state:
          type: string
        endpoint_ref:
          type: string
          description: Redacted endpoint reference; never a credential.
        observed_at:
          type: string
          format: date-time
        metadata:
          type: object
          additionalProperties: true
    GuardReach:
      type: object
      description: >-
        kombify Guard reach, persisted and never derived client-side: whether
        the server's kombify.me address answers through the Guard relay and
        whether the server is listed as a Connect resource. `ready` is shown as
        "Reachable and governed". A reach failure never blocks Guard enrollment
        or execution and never changes the server lifecycle. Absent on
        deployments without a Cloud connection.
      required:
        - state
        - kombify_me
        - connect
        - updated_at
      properties:
        state:
          type: string
          enum:
            - not_enrolled
            - pending
            - failed
            - ready
            - revoked
            - not_enabled
          description: >-
            pending is reach_pending, failed is reach_failed (see the reason
            codes of the two targets). not_enabled is a server the owner has not
            published at a kombify.me address (the default): no route exists and
            nothing is served.
        generation:
          type: integer
          format: int64
          description: Binding generation, raised when the Guard key or pairing changes.
        public:
          type: object
          description: >-
            The owner's publication choice; nothing is published until it is
            enabled with a service and a port.
          required:
            - enabled
          properties:
            enabled:
              type: boolean
            service:
              type: string
              description: The route label the owner chose.
            scheme:
              type: string
              enum:
                - http
                - https
            target_port:
              type: integer
              minimum: 1
              maximum: 65535
              description: The port of the service on the Guard host's loopback.
            enabled_by:
              type: string
            enabled_at:
              type: string
              format: date-time
        kombify_me:
          $ref: '#/components/schemas/GuardReachTarget'
        connect:
          $ref: '#/components/schemas/GuardReachTarget'
        relay:
          type: object
          description: The Guard's own report of its relay connection.
          required:
            - state
          properties:
            state:
              type: string
              enum:
                - connecting
                - connected
                - denied
                - stopped
            reason_code:
              type: string
            reported_at:
              type: string
              format: date-time
        updated_at:
          type: string
          format: date-time
    ServerSecurity:
      type: object
      description: >-
        The persisted host security posture of a server with a kombify Guard:
        the StackKits `stackkit.host-security-evidence/v1` the Guard last
        reported, judged by the control plane at read time. Never derived from
        the heartbeat and never client-side: a connected, healthy server without
        fresh evidence is `unknown`. Evidence past `expires_at`, an older
        StackKits CLI without the command, a document that could not be read and
        an incomplete baseline are all `unknown` with a `reason_code`; `unknown`
        is never compliant. Absent on a server without a Guard.
      required:
        - state
        - findings
      properties:
        state:
          type: string
          enum:
            - compliant
            - drifted
            - unknown
            - exception_only
        reason_code:
          type: string
          description: >-
            Why the state is unknown: not_observed, evidence_stale,
            incomplete_evidence, stackkit_cli_unsupported,
            stackkit_runtime_unavailable, workspace_unavailable,
            executor_unavailable, observation_failed or evidence_rejected.
        baseline_version:
          type: string
        observed_at:
          type: string
          format: date-time
        expires_at:
          type: string
          format: date-time
        findings:
          type: array
          description: >-
            The controls that are not compliant. Empty while the evidence is
            stale.
          items:
            $ref: '#/components/schemas/ServerSecurityFinding'
    ServerRecovery:
      type: object
      description: >-
        Persisted recoverability evidence. A snapshot's age never proves that a
        restore works: only a verified restore-drill receipt speaks for that.
      required:
        - backup
        - restore_drill
      properties:
        backup:
          type: object
          required:
            - state
            - policy_max_age
          properties:
            state:
              type: string
              enum:
                - fresh
                - stale
                - unknown
            reason_code:
              type: string
              description: >-
                Why it is unknown: not_observed, observation_stale, no_receipt,
                clock_skew or the Guard's reason.
            last_snapshot_at:
              type: string
              format: date-time
            policy_max_age:
              type: string
              description: ISO 8601 duration after which a snapshot receipt is stale.
        restore_drill:
          type: object
          required:
            - state
            - policy_max_age
          properties:
            state:
              type: string
              enum:
                - verified
                - stale
                - unknown
            reason_code:
              type: string
            verified_at:
              type: string
              format: date-time
            policy_max_age:
              type: string
              description: ISO 8601 duration after which a verified receipt is stale.
    ServerUpdates:
      type: object
      required:
        - guard
        - os
      properties:
        guard:
          type: object
          required:
            - signed
            - state
          properties:
            version:
              type: string
            signed:
              type: boolean
              description: >-
                True when the Guard's update path admits only signed releases
                (the privilege-split layout without an unsigned-build opt-in).
            state:
              type: string
              enum:
                - current
                - staged
                - trial
                - denied
                - rolled_back
                - layout_rolled_back
                - recovery_needed
                - unknown
        os:
          type: object
          description: >-
            Read from the security evidence controls; a field the evidence does
            not state is absent.
          properties:
            pending_security_updates:
              type: integer
              minimum: 0
            reboot_required:
              type: boolean
            last_unattended_run:
              type: string
              format: date-time
    ServerCapabilities:
      type: object
      description: >-
        The Guard facts the control plane persisted for the server's worker,
        tenant scoped. No token hash and no key material;
        `credential_generation` is the integer the fenced credential rotation
        must echo as `expected_credential_generation`. Absent on a server
        without a Guard worker.
      required:
        - identity_binding
        - credential_generation
      properties:
        identity_binding:
          type: string
          enum:
            - key_bound
            - legacy_bearer
            - unknown
          description: How the Guard last proved its identity.
        credential_generation:
          type: integer
          format: int64
          minimum: 0
        identity_upgrade:
          type: object
          description: >-
            Present while the server authenticates with its bearer credential
            alone: it reports and updates itself but receives no mutating
            command until the owner approves its identity key.
          required:
            - required
            - code
          properties:
            required:
              type: boolean
            code:
              type: string
              enum:
                - guard_identity_upgrade_required
        guard_operations:
          type: object
          description: >-
            The Guard's durable operation journal health. `durable` is true only
            while the journal is writable and nothing is unresolved.
          required:
            - contract
            - durable
            - unresolved_outcome_unknown
            - unacked_results
            - in_flight
          properties:
            contract:
              type: string
            state:
              type: string
              description: The journal state.
            durable:
              type: boolean
            unresolved_outcome_unknown:
              type: integer
              minimum: 0
            unacked_results:
              type: integer
              minimum: 0
            in_flight:
              type: integer
              minimum: 0
            journal_bytes:
              type: integer
              format: int64
            journal_budget_bytes:
              type: integer
              format: int64
            reason:
              type: string
        guard_posture:
          type: object
          description: >-
            How the Guard is isolated and how its latest update went. A Guard
            that reports nothing is legacy_root, never isolated.
          required:
            - mode
            - reported
            - deny_mutations
          properties:
            mode:
              type: string
              enum:
                - split
                - legacy_root
                - unavailable
            reported:
              type: boolean
            deny_mutations:
              type: boolean
            update_state:
              type: string
            update_version:
              type: string
            update_reason:
              type: string
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - INTERNAL_ERROR
                - NOT_FOUND
                - BAD_REQUEST
                - UNAUTHORIZED
                - FORBIDDEN
                - CONFLICT
                - VALIDATION_ERROR
                - RATE_LIMITED
                - SERVICE_UNAVAILABLE
                - METHOD_NOT_ALLOWED
            message:
              type: string
            details:
              description: Additional error context (validation errors, etc.)
    GuardReachTarget:
      type: object
      required:
        - state
      properties:
        state:
          type: string
          enum:
            - pending
            - registered
            - failed
            - revoked
            - not_enabled
        address:
          type: string
          description: kombify.me address (kombify_me target, registered only).
        node_id:
          type: string
          description: Connect techstack-node id (connect target, registered only).
        reason_code:
          type: string
          description: Stable structured reason for a pending or failed target.
    ServerSecurityFinding:
      type: object
      required:
        - control
        - state
        - severity
        - expected
        - observed
        - remediation
      properties:
        control:
          type: string
          enum:
            - firewall.default_inbound
            - ssh.password_authentication
            - ssh.root_login
            - ssh.port
            - bruteforce.fail2ban
            - updates.unattended_upgrades
            - updates.pending_security
            - updates.reboot_required
            - kernel.sysctl
            - exposure.listeners
            - exposure.published_ports
            - tls.certificate_expiry
        state:
          type: string
          enum:
            - drifted
            - unknown
            - exception
        severity:
          type: string
          enum:
            - critical
            - high
            - medium
            - low
            - info
        expected:
          type: string
        observed:
          type: string
        reason_code:
          type: string
          description: >-
            A stable code for a finding that needs a specific follow-up, for
            example no_authorized_key or exposed_published_port.
        remediation:
          type: object
          required:
            - capability
          properties:
            capability:
              type: string
              enum:
                - automatic
                - manual
                - none
              description: >-
                automatic controls can be repaired through the security repair
                route; manual ones need another command or the owner.
            action:
              type: string
        exception:
          type: object
          description: Present when an owner-approved exception covers the control.
          required:
            - owner
            - reason
            - expires_at
          properties:
            owner:
              type: string
            reason:
              type: string
            expires_at:
              type: string
              format: date-time
  responses:
    Unauthorized:
      description: Authentication required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        OIDC/JWKS bearer token. Self-hosted defaults to Pocket ID; SaaS uses
        Auth0 through the edge. PocketBase JWT is legacy migration compatibility
        only.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.