Set up an ordinary fleet without configuration questions; preserve prior stop intent#

Private controller API. Call this route through the user’s Unix socket, locally or over SSH. It is not exposed on the server’s public origin.

PropertyValue
Servicefleetd
Operationsetup
MethodPOST
Path/api/setup
Authenticationpublic
Success status200
Response dataUnpaginated value
Request formatjson
Maximum request body1048576 bytes (service default)
Permission codesNone declared

Listed permission codes are alternatives, not token scopes. The service also checks access to the requested records and rejects stale revisions or controller generations.

Path parameters#

empty object; unknown fields rejected

Validation#

check.empty

Referenced definitions:

Query parameters#

custom validation: none ; see function below

Query parameters are URL text. The validation function below specifies their format, defaults and combinations. Pagination applies only to operations that use it.

Additional checks#

The following checks apply in addition to the field limits.

Constraint on value:

export function none(input: unknown) {
    const parsed = listQuery([])(input);
    return parsed.ok ? success({}) : parsed;
}

Validation#

none

Referenced definitions:

Request body#

object; fields below; unknown fields rejected ( setupInput )

Field pathRepresentation and constraints
descriptorobject; fields below; unknown fields rejected ( setupDescriptorSchema )
descriptor.schemaVersioncustom validation: schemaVersion ; see function below
descriptor.serverstring; 1–2048 UTF-16 units; well-formed Unicode; no C0/DEL controls; constraint: Use an exact HTTPS or loopback HTTP origin ( setupOrigin )
descriptor.ownerMatrixIdwell-formed Matrix user ID; maximum 255 UTF-16 units
descriptor.packageobject; fields below; unknown fields rejected
descriptor.package.name@ctlflow/fleet
descriptor.package.versionstring; 1–100 UTF-16 units; well-formed Unicode; no C0/DEL controls; constraint: Use one exact npm version ( setupVersion )
descriptor.instructionsplain-text string; at most 131072 UTF-8 bytes; allowed whitespace controls only
workspacestring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls
configurationstring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls; optional property

Additional checks#

The following checks apply in addition to the field limits.

Constraint on descriptor.schemaVersion:

value => value === 1 ? success(1) : failure('invalid', 'Unsupported setup descriptor')

Constraint on descriptor.server:

value => { const parsed = endpoint(value); return parsed.ok && parsed.value === value; }

Constraint on descriptor.package.version:

value => /^\d+\.\d+\.\d+(?:-[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*)?$/u.test(value)

Validation#

setupInput

Referenced definitions:

Response data#

object; fields below; unknown fields rejected ( setupResult )

Field pathRepresentation and constraints
fleetobject; fields below; unknown fields rejected ( fleetView )
fleet.fleetIdlowercase opaque UUID
fleet.fleetKeylowercase name; pattern [a-z][a-z0-9-]{0,39}
fleet.labelstring; 1–100 UTF-16 units; well-formed Unicode; no C0/DEL controls
fleet.directorystring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls
fleet.revisionexact JSON integer; 0…9007199254740991
fleet.controllerobject; fields below; unknown fields rejected ( controller )
fleet.controller.namestring; 1–100 UTF-16 units; well-formed Unicode; no C0/DEL controls
fleet.controller.metadatacustom validation: metadata ; see function below; optional property
fleet.resumeInstanceKeysarray; 0–100 entries; item: lowercase name; pattern [a-z][a-z0-9-]{0,39}; JSON null permitted
fleet.phasestopped or starting or awaiting-approval or running or sleeping or waking or stopping or failed ( phase )
fleet.instancesarray; 0–100 entries; item: object; fields below; unknown fields rejected ( instanceView )
fleet.instances[].instanceobject; fields below; unknown fields rejected ( instance )
fleet.instances[].instance.keylowercase name; pattern [a-z][a-z0-9-]{0,39}
fleet.instances[].instance.namelowercase name; pattern [a-z][a-z0-9-]{0,39}
fleet.instances[].instance.definitionlowercase name; pattern [a-z][a-z0-9-]{0,39}
fleet.instances[].instance.workareastring; 1–1024 UTF-16 units; well-formed Unicode; no C0/DEL controls
fleet.instances[].instance.workspacestring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls; optional property
fleet.instances[].instance.runtimeOptionscustom validation: runtimeOptions ; see function below; optional property
fleet.instances[].instance.listenerOptionsobject; fields below; unknown fields rejected; optional property
fleet.instances[].instance.listenerOptions.historyModeshared or per-room; optional property
fleet.instances[].phasestopped or starting or awaiting-approval or running or sleeping or waking or stopping or failed ( phase )
fleet.instances[].listenerActiveboolean
fleet.instances[].desiredActiveboolean
fleet.instances[].lastActivityAtexact JSON integer; 0…9007199254740991; JSON null permitted
fleet.instances[].historyAvailableboolean; JSON null permitted
fleet.instances[].sessionIdstring; 1–200 UTF-16 units; well-formed Unicode; no C0/DEL controls; JSON null permitted
fleet.instances[].errorstring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls; JSON null permitted
fleet.instances[].startedAtexact JSON integer; 0…9007199254740991; JSON null permitted
fleet.errorstring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls; JSON null permitted
fleet.connectionobject; fields below; unknown fields rejected
fleet.connection.connectedboolean
fleet.connection.deliveryEnabledboolean
fleet.connection.revisionexact JSON integer; 0…9007199254740991; JSON null permitted
fleet.connection.errorstring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls; JSON null permitted
operationobject; fields below; unknown fields rejected; constraint: Only an explicit software update supplies its installed release directory ( operationView ); JSON null permitted
operation.operationIdlowercase opaque UUID
operation.targetobject; fields below; unknown fields rejected ( target )
operation.target.kindfleet or agent or daemon
operation.target.fleetIdlowercase opaque UUID; optional property
operation.target.instanceKeylowercase name; pattern [a-z][a-z0-9-]{0,39}; optional property
operation.actionenroll or start or stop or reset or update
operation.expectedRevisionexact JSON integer; 0…9007199254740991
operation.releaseDirectorystring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls; constraint: Release directory must be an absolute normalized path ( releaseDirectory ); optional property
operation.receiptPendingcustom validation; see function below; optional property
operation.statusaccepted or running or awaiting-approval or succeeded or failed
operation.createdAtexact JSON integer; 0…9007199254740991
operation.completedAtexact JSON integer; 0…9007199254740991; JSON null permitted
operation.approvalobject; fields below; unknown fields rejected; JSON null permitted
operation.approval.urlstring; 1–2048 UTF-16 units; well-formed Unicode; no C0/DEL controls
operation.approval.codestring; 12–12 UTF-16 units; well-formed Unicode; no C0/DEL controls
operation.errorsarray; 0–100 entries; item: object; fields below; unknown fields rejected
operation.errors[].instanceKeylowercase name; pattern [a-z][a-z0-9-]{0,39}; JSON null permitted
operation.errors[].codestring; 1–100 UTF-16 units; well-formed Unicode; no C0/DEL controls
operation.errors[].messagestring; 1–4096 UTF-16 units; well-formed Unicode; no C0/DEL controls
statusstarting or ready or stopped

Additional checks#

The following checks apply in addition to the field limits.

Constraint on fleet.controller.metadata:

function metadata(input: unknown): Result<Record<string, string>> {
    if (!input || typeof input !== 'object' || Array.isArray(input) || Object.keys(input).length > 16)
        return failure('invalid', 'Controller metadata supports at most 16 text fields');
    const output: Record<string, string> = {};
    for (const [key, value] of Object.entries(input)) {
        if (!/^[a-z][a-z0-9-]{0,39}$/u.test(key) || !check.text(256, 0)(value).ok || typeof value !== 'string')
            return failure('invalid', 'Invalid controller metadata');
        output[key] = value;
    }
    return success(output);
}

Constraint on fleet.instances[].instance.runtimeOptions:

(input: unknown): Result<Record<string, unknown>> => input && typeof input === 'object' && !Array.isArray(input) ? success(input as Record<string, unknown>) : failure('invalid', 'Expected runtime options')

Constraint on operation:

value => (value.action === 'update') === (value.releaseDirectory !== undefined)

Constraint on operation.releaseDirectory:

value => value.startsWith('/') && !value.includes('\\')
    && value.split('/').slice(1).every(segment => segment && segment !== '.' && segment !== '..')

Constraint on operation.receiptPending:

input => input === true ? success(true) : failure('invalid', 'Only unacknowledged controller requests are pinned')

Validation#

setupResult

Referenced definitions:

Response envelope#

A successful JSON response contains data and meta. Replace the data placeholder below with the response fields described above. Errors contain error instead of data.

{
  "data": "<value matching the response-data validator>",
  "meta": {
    "requestId": "00000000-0000-0000-0000-000000000001"
  }
}