openapi: 3.1.0 info: title: betterNAS Foundation API version: 0.1.0 summary: Foundation contract for node registration, export metadata, and profile issuance. servers: - url: http://localhost:8081 paths: /health: get: operationId: getControlPlaneHealth responses: "200": description: Control-plane health /version: get: operationId: getControlPlaneVersion responses: "200": description: Control-plane version /api/v1/nodes: get: operationId: listNodes security: - UserSession: [] responses: "200": description: Node list content: application/json: schema: type: array items: $ref: "#/components/schemas/NasNode" "401": description: Unauthorized /api/v1/nodes/register: post: operationId: registerNode security: - UserSession: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/NodeRegistrationRequest" responses: "200": description: Registered node content: application/json: schema: $ref: "#/components/schemas/NasNode" "401": description: Unauthorized /api/v1/nodes/{nodeId}/heartbeat: post: operationId: recordNodeHeartbeat security: - UserSession: [] parameters: - in: path name: nodeId required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/NodeHeartbeatRequest" responses: "204": description: Heartbeat accepted "401": description: Unauthorized /api/v1/nodes/{nodeId}/exports: put: operationId: syncNodeExports security: - UserSession: [] parameters: - in: path name: nodeId required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/NodeExportsRequest" responses: "200": description: Export inventory accepted content: application/json: schema: type: array items: $ref: "#/components/schemas/StorageExport" "401": description: Unauthorized /api/v1/exports: get: operationId: listExports security: - UserSession: [] responses: "200": description: Export list content: application/json: schema: type: array items: $ref: "#/components/schemas/StorageExport" "401": description: Unauthorized /api/v1/mount-profiles/issue: post: operationId: issueMountProfile security: - UserSession: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MountProfileRequest" responses: "200": description: Mount profile content: application/json: schema: $ref: "#/components/schemas/MountProfile" "401": description: Unauthorized /api/v1/cloud-profiles/issue: post: operationId: issueCloudProfile security: - UserSession: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CloudProfileRequest" responses: "200": description: Cloud profile content: application/json: schema: $ref: "#/components/schemas/CloudProfile" "401": description: Unauthorized components: securitySchemes: UserSession: type: http scheme: bearer description: Bearer session token returned by the username and password auth endpoints. schemas: NasNode: type: object required: - id - machineId - displayName - agentVersion - status - lastSeenAt - directAddress - relayAddress properties: id: type: string machineId: type: string displayName: type: string agentVersion: type: string status: type: string enum: [online, offline, degraded] lastSeenAt: type: string directAddress: type: - string - "null" relayAddress: type: - string - "null" StorageExport: type: object required: - id - nasNodeId - label - path - protocols - capacityBytes - tags properties: id: type: string nasNodeId: type: string label: type: string path: type: string mountPath: type: string protocols: type: array items: type: string enum: [webdav] capacityBytes: type: - integer - "null" tags: type: array items: type: string MountProfile: type: object required: - id - exportId - protocol - displayName - mountUrl - readonly - credential properties: id: type: string exportId: type: string protocol: type: string enum: [webdav] displayName: type: string mountUrl: type: string readonly: type: boolean credential: $ref: "#/components/schemas/MountCredential" MountCredential: type: object required: - mode - username - password - expiresAt properties: mode: type: string enum: [basic-auth] username: type: string password: type: string expiresAt: type: string CloudProfile: type: object required: - id - exportId - provider - baseUrl - path properties: id: type: string exportId: type: string provider: type: string enum: [nextcloud] baseUrl: type: string path: type: string StorageExportInput: type: object required: - label - path - protocols - capacityBytes - tags properties: label: type: string path: type: string mountPath: type: string protocols: type: array items: type: string enum: [webdav] capacityBytes: type: - integer - "null" tags: type: array items: type: string NodeRegistrationRequest: type: object required: - machineId - displayName - agentVersion - directAddress - relayAddress properties: machineId: type: string displayName: type: string agentVersion: type: string directAddress: type: - string - "null" relayAddress: type: - string - "null" NodeExportsRequest: type: object required: - exports properties: exports: type: array items: $ref: "#/components/schemas/StorageExportInput" NodeHeartbeatRequest: type: object required: - nodeId - status - lastSeenAt properties: nodeId: type: string status: type: string enum: [online, offline, degraded] lastSeenAt: type: string MountProfileRequest: type: object required: - exportId properties: exportId: type: string CloudProfileRequest: type: object required: - userId - exportId - provider properties: userId: type: string exportId: type: string provider: type: string enum: [nextcloud]