@opensoha/contracts 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/COMPATIBILITY.md CHANGED
@@ -364,6 +364,31 @@ role migration and consumer conformance prove no active dependency.
364
364
 
365
365
  ## Consumer Adoption
366
366
 
367
+ Connection tests and Compute provider health checks return HTTP 200 with
368
+ `ConnectionCheckResultEnvelope` after each fresh probe. Consumers read `healthy`
369
+ and the diagnostic fields directly; no task or task log is created. The Compute
370
+ endpoint still accepts `Idempotency-Key` for request compatibility, but it no
371
+ longer replays stored checks. Operation/audit logs and existing task history are
372
+ preserved. HTTP 202 task envelopes remain documented for older servers. Core,
373
+ Web and CLI must adopt the new HTTP 200 result together. Discovery and asset
374
+ synchronization remain asynchronous. The Go SDK
375
+ `CheckComputeProviderInstanceHealth` method now returns `ConnectionCheckResult`
376
+ instead of `ComputeTaskView`; callers consuming its fields must update with Core
377
+ to preserve the immediate health result and diagnostic details. Upgrade Core
378
+ before these clients. The SDK rejects legacy task responses with a server-upgrade
379
+ error instead of reporting an empty health result; the 202 schema documents older
380
+ server wire behavior and does not promise task polling in the new check method.
381
+
382
+ Docker port mapping creation reserves control-plane metadata synchronously; it
383
+ does not enqueue `port_reserve` or bind a host port. Existing operation kinds and
384
+ historical records remain compatible. Service log readers use the existing
385
+ project runtime logs API. The service-action API accepts start, stop and restart;
386
+ `logs` returns an invalid-argument error directing callers to the direct project
387
+ log query instead of creating a task. Compute resource actions expose only these
388
+ mutations. Historical `connection_test`, `port_reserve`, and `service_action`
389
+ with action `logs` remain readable, but their operation state is not retryable
390
+ and retry requests are rejected without requeueing or appending task logs.
391
+
367
392
  Recommended adoption flow:
368
393
 
369
394
  1. Change contracts and fixtures here first.
@@ -402,9 +427,11 @@ behavior.
402
427
 
403
428
  ## Contracts-first consumer revisions
404
429
 
405
- `compat/consumer-revisions.json` pins a reviewed consumer commit when a contracts
406
- release introduces APIs implemented by that consumer's pending change. Both CI
407
- and release use the same commit and run the complete existing consumer checks.
408
- Unlisted consumers use `main`. Replace the pin with `main` (or remove it) once the
409
- matching consumer changes reach its default branch; do not skip failed checks to
410
- resolve a release-order dependency.
430
+ `compat/consumer-revisions.json` pins a reviewed full commit SHA for every consumer
431
+ in the executable matrix. CI and release use `scripts/select-consumer-revision.mjs`;
432
+ missing or invalid revisions fail instead of falling back to `main`. Update a pin
433
+ only with an explicit compatibility reason and successful matrix evidence.
434
+
435
+ Manual CI may select `consumer_mode=latest` for separate integration evidence.
436
+ This does not rewrite the fixed manifest or replace fixed-combination acceptance.
437
+ Record the actual contracts and consumer commits, not only the selected mode.
package/README.md CHANGED
@@ -169,6 +169,7 @@ npm run check:consumers -- --consumer soha --require-all
169
169
  npm run check:consumers -- --consumer soha-web --require-all
170
170
  npm run check:consumers -- --consumer soha-cli --require-all
171
171
  npm run check:consumers -- --consumer soha-agent --require-all
172
+ npm run check:consumers -- --consumer soha-skills --require-all
172
173
  ```
173
174
 
174
175
  Go consumers run in a temporary `go.work` that replaces the contracts module
@@ -1,3 +1,7 @@
1
1
  {
2
- "soha": "d675a708806072a2fee42e3c2c00309091a8cfb9"
2
+ "soha": "d675a708806072a2fee42e3c2c00309091a8cfb9",
3
+ "soha-web": "816ec0fb82e6e804f0f66d47d3446a7b5baeabc1",
4
+ "soha-cli": "1c9b760c986a9c1a5148db55b72ab99d23edd7a3",
5
+ "soha-agent": "af1efc0b0cd6bb544153429fa28244dd6cc81ac7",
6
+ "soha-skills": "0345171ee1c9f23ab5d4350767395d0919dfb21c"
3
7
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.18",
2
+ "version": "0.1.19",
3
3
  "schemas": {
4
4
  "plugins/plugin-manifest.schema.json": {
5
5
  "rootRequired": ["id", "name", "publisher", "type", "version"],
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.18",
2
+ "version": "0.1.19",
3
3
  "generatedFrom": "openapi/soha-api.yaml",
4
4
  "entries": [
5
5
  {
@@ -0,0 +1 @@
1
+ {"status":"healthy","checkedAt":"2026-09-22T00:00:00Z"}
@@ -0,0 +1 @@
1
+ {"healthy":true,"status":"healthy","checkedAt":"2026-09-22T00:00:00Z","id":"task-1"}
@@ -0,0 +1 @@
1
+ {"healthy":false,"status":"unavailable","message":"Connection refused","reason":"network","checkedAt":"2026-09-22T00:00:00Z"}
@@ -0,0 +1 @@
1
+ {"healthy":true,"status":"healthy","checkedAt":"2026-09-22T00:00:00Z"}
@@ -0,0 +1,9 @@
1
+ {
2
+ "appTitle": "Soha",
3
+ "sidebarTitle": "Soha",
4
+ "loginLogoUrl": "/logo.svg",
5
+ "expandedLogoUrl": "/logo.svg",
6
+ "collapsedLogoUrl": "/logo.svg",
7
+ "faviconUrl": "/logo.svg",
8
+ "darkExpandedLogoUrl": true
9
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "appTitle": "Soha",
3
+ "sidebarTitle": "Soha",
4
+ "loginLogoUrl": "/logo.svg",
5
+ "expandedLogoUrl": "/logo.svg",
6
+ "collapsedLogoUrl": "/logo.svg",
7
+ "faviconUrl": "/logo.svg",
8
+ "darkExpandedLogoUrl": "/brand-dark.svg",
9
+ "darkCollapsedLogoUrl": "/mark-dark.svg"
10
+ }
@@ -16,7 +16,7 @@ import (
16
16
  "time"
17
17
  )
18
18
 
19
- const defaultUserAgent = "opensoha-contracts/0.1.18"
19
+ const defaultUserAgent = "opensoha-contracts/0.1.19"
20
20
 
21
21
  type Client struct {
22
22
  BaseURL string
@@ -594,8 +594,16 @@ func (c *Client) GetComputeProviderInstance(ctx context.Context, domain ComputeP
594
594
  return out.Data, nil
595
595
  }
596
596
 
597
- func (c *Client) CheckComputeProviderInstanceHealth(ctx context.Context, domain ComputeProviderDomain, providerKey, instanceRef, idempotencyKey string, req ComputeProviderReadRequest) (ComputeTaskView, error) {
598
- return c.mutateComputeProviderInstance(ctx, domain, providerKey, instanceRef, "health-checks", idempotencyKey, req)
597
+ func (c *Client) CheckComputeProviderInstanceHealth(ctx context.Context, domain ComputeProviderDomain, providerKey, instanceRef, idempotencyKey string, req ComputeProviderReadRequest) (ConnectionCheckResult, error) {
598
+ var out ConnectionCheckResultEnvelope
599
+ path := computeProviderInstancePath(domain, providerKey, instanceRef) + "/health-checks"
600
+ if err := c.doJSONWithHeaders(ctx, http.MethodPost, path, true, req, &out, idempotencyHeader(idempotencyKey)); err != nil {
601
+ return ConnectionCheckResult{}, err
602
+ }
603
+ if out.Data.CheckedAt.IsZero() || strings.TrimSpace(out.Data.Status) == "" {
604
+ return ConnectionCheckResult{}, fmt.Errorf("connection health check returned no synchronous result; upgrade the server before using this client")
605
+ }
606
+ return out.Data, nil
599
607
  }
600
608
 
601
609
  func (c *Client) DiscoverComputeProviderInstance(ctx context.Context, domain ComputeProviderDomain, providerKey, instanceRef, idempotencyKey string, req ComputeProviderDiscoverRequest) (ComputeTaskView, error) {
@@ -414,7 +414,7 @@ func TestComputeInventoryClientSurface(t *testing.T) {
414
414
  if key := r.Header.Get("Idempotency-Key"); key != "health-key-1" {
415
415
  t.Fatalf("health Idempotency-Key = %q", key)
416
416
  }
417
- writeJSON(t, w, computeTaskEnvelopeFixture("health-task"))
417
+ writeJSON(t, w, map[string]any{"data": map[string]any{"healthy": true, "status": "healthy", "checkedAt": "2026-09-22T00:00:00Z"}})
418
418
  case 8:
419
419
  assertCommonRequest(t, r, http.MethodPost, "/api/v1/compute/provider-instances/virtualization/pve/connection%2Fone/discoveries")
420
420
  if key := r.Header.Get("Idempotency-Key"); key != "discover-key-1" {
@@ -458,8 +458,8 @@ func TestComputeInventoryClientSurface(t *testing.T) {
458
458
  if _, err := client.GetComputeProviderInstance(ctx, ComputeProviderDomainVirtualization, "pve", "connection/one"); err != nil {
459
459
  t.Fatal(err)
460
460
  }
461
- if _, err := client.CheckComputeProviderInstanceHealth(ctx, ComputeProviderDomainVirtualization, "pve", "connection/one", "health-key-1", ComputeProviderReadRequest{ExpectedGeneration: 1}); err != nil {
462
- t.Fatal(err)
461
+ if result, err := client.CheckComputeProviderInstanceHealth(ctx, ComputeProviderDomainVirtualization, "pve", "connection/one", "health-key-1", ComputeProviderReadRequest{ExpectedGeneration: 1}); err != nil || !result.Healthy || result.Status != "healthy" || result.CheckedAt.IsZero() {
462
+ t.Fatalf("CheckComputeProviderInstanceHealth = %#v, %v", result, err)
463
463
  }
464
464
  if _, err := client.DiscoverComputeProviderInstance(ctx, ComputeProviderDomainVirtualization, "pve", "connection/one", "discover-key-1", ComputeProviderDiscoverRequest{ExpectedGeneration: 1}); err != nil {
465
465
  t.Fatal(err)
@@ -475,6 +475,29 @@ func TestComputeInventoryClientSurface(t *testing.T) {
475
475
  }
476
476
  }
477
477
 
478
+ func TestComputeProviderHealthPreservesDiagnostics(t *testing.T) {
479
+ client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) {
480
+ writeJSON(t, w, map[string]any{"data": map[string]any{
481
+ "healthy": false, "status": "degraded", "checkedAt": "2026-09-22T00:00:00Z",
482
+ "httpStatus": 401, "reason": "authentication_failed", "message": "Credentials rejected", "nextAction": "Update credentials",
483
+ }})
484
+ })
485
+ result, err := client.CheckComputeProviderInstanceHealth(context.Background(), ComputeProviderDomainVirtualization, "pve", "connection-1", "", ComputeProviderReadRequest{})
486
+ if err != nil || result.Healthy || result.Status != "degraded" || result.HTTPStatus != 401 || result.Reason != "authentication_failed" || result.Message != "Credentials rejected" || result.NextAction != "Update credentials" || result.CheckedAt.IsZero() {
487
+ t.Fatalf("CheckComputeProviderInstanceHealth = %#v, %v", result, err)
488
+ }
489
+ }
490
+
491
+ func TestComputeProviderHealthRejectsLegacyTask(t *testing.T) {
492
+ client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) {
493
+ w.WriteHeader(http.StatusAccepted)
494
+ writeJSON(t, w, computeTaskEnvelopeFixture("health-task"))
495
+ })
496
+ if _, err := client.CheckComputeProviderInstanceHealth(context.Background(), ComputeProviderDomainVirtualization, "pve", "connection-1", "", ComputeProviderReadRequest{}); err == nil || !strings.Contains(err.Error(), "upgrade the server") {
497
+ t.Fatalf("legacy task response should require a server upgrade, got %v", err)
498
+ }
499
+ }
500
+
478
501
  func TestStreamComputeTask(t *testing.T) {
479
502
  client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) {
480
503
  if r.Method != http.MethodGet || r.URL.EscapedPath() != "/api/v1/compute/tasks/virtualization/task%2Fone/stream" {
@@ -12775,11 +12775,17 @@ type BrandingAssetUploadEnvelope struct {
12775
12775
  type BrandingSettings struct {
12776
12776
  AppTitle string `json:"appTitle"`
12777
12777
  CollapsedLogoURL string `json:"collapsedLogoUrl"`
12778
- ExpandedLogoURL string `json:"expandedLogoUrl"`
12779
- FaviconURL string `json:"faviconUrl"`
12780
- LoginLogoURL string `json:"loginLogoUrl"`
12781
- SidebarTitle string `json:"sidebarTitle"`
12782
- Slogan string `json:"slogan,omitempty"`
12778
+
12779
+ // DarkCollapsedLogoURL Optional dark-theme compact logo. Empty or absent uses collapsedLogoUrl.
12780
+ DarkCollapsedLogoURL string `json:"darkCollapsedLogoUrl,omitempty"`
12781
+
12782
+ // DarkExpandedLogoURL Optional dark-theme expanded logo. Empty or absent uses expandedLogoUrl.
12783
+ DarkExpandedLogoURL string `json:"darkExpandedLogoUrl,omitempty"`
12784
+ ExpandedLogoURL string `json:"expandedLogoUrl"`
12785
+ FaviconURL string `json:"faviconUrl"`
12786
+ LoginLogoURL string `json:"loginLogoUrl"`
12787
+ SidebarTitle string `json:"sidebarTitle"`
12788
+ Slogan string `json:"slogan,omitempty"`
12783
12789
  }
12784
12790
 
12785
12791
  // BrandingSettingsEnvelope defines model for BrandingSettingsEnvelope.
@@ -14026,6 +14032,23 @@ type ComputeWarning struct {
14026
14032
  Message string `json:"message,omitempty"`
14027
14033
  }
14028
14034
 
14035
+ // ConnectionCheckResult Current connection health from a synchronous probe. This result is not a task and has no task identifier or lifecycle actions.
14036
+ type ConnectionCheckResult struct {
14037
+ CheckedAt time.Time `json:"checkedAt"`
14038
+ Healthy bool `json:"healthy"`
14039
+ HTTPStatus int `json:"httpStatus,omitempty"`
14040
+ Message string `json:"message,omitempty"`
14041
+ NextAction string `json:"nextAction,omitempty"`
14042
+ Reason string `json:"reason,omitempty"`
14043
+ Status string `json:"status"`
14044
+ }
14045
+
14046
+ // ConnectionCheckResultEnvelope defines model for ConnectionCheckResultEnvelope.
14047
+ type ConnectionCheckResultEnvelope struct {
14048
+ // Data Current connection health from a synchronous probe. This result is not a task and has no task identifier or lifecycle actions.
14049
+ Data ConnectionCheckResult `json:"data"`
14050
+ }
14051
+
14029
14052
  // CreatedPersonalAccessToken defines model for CreatedPersonalAccessToken.
14030
14053
  type CreatedPersonalAccessToken struct {
14031
14054
  Token PersonalAccessToken `json:"token"`
@@ -26761,11 +26784,17 @@ type UpdateAIWorkbenchModelRequest struct {
26761
26784
  type UpdateBrandingSettingsRequest struct {
26762
26785
  AppTitle string `json:"appTitle"`
26763
26786
  CollapsedLogoURL string `json:"collapsedLogoUrl"`
26764
- ExpandedLogoURL string `json:"expandedLogoUrl"`
26765
- FaviconURL string `json:"faviconUrl"`
26766
- LoginLogoURL string `json:"loginLogoUrl"`
26767
- SidebarTitle string `json:"sidebarTitle"`
26768
- Slogan string `json:"slogan,omitempty"`
26787
+
26788
+ // DarkCollapsedLogoURL Optional dark-theme compact logo. Empty or absent clears the override.
26789
+ DarkCollapsedLogoURL string `json:"darkCollapsedLogoUrl,omitempty"`
26790
+
26791
+ // DarkExpandedLogoURL Optional dark-theme expanded logo. Empty or absent clears the override.
26792
+ DarkExpandedLogoURL string `json:"darkExpandedLogoUrl,omitempty"`
26793
+ ExpandedLogoURL string `json:"expandedLogoUrl"`
26794
+ FaviconURL string `json:"faviconUrl"`
26795
+ LoginLogoURL string `json:"loginLogoUrl"`
26796
+ SidebarTitle string `json:"sidebarTitle"`
26797
+ Slogan string `json:"slogan,omitempty"`
26769
26798
  }
26770
26799
 
26771
26800
  // UpdateLoginProvidersSettingsRequest defines model for UpdateLoginProvidersSettingsRequest.
@@ -1085,6 +1085,7 @@ export interface paths {
1085
1085
  get: operations["getApplication"];
1086
1086
  put: operations["updateApplication"];
1087
1087
  post?: never;
1088
+ /** @description Deletes the application and its owned configuration and history. Does not uninstall cluster workloads. Unfinished delivery tasks or external references prevent deletion. */
1088
1089
  delete: operations["deleteApplication"];
1089
1090
  options?: never;
1090
1091
  head?: never;
@@ -6223,6 +6224,7 @@ export interface paths {
6223
6224
  };
6224
6225
  get?: never;
6225
6226
  put?: never;
6227
+ /** @description Requires docker.services.logs. Reads bounded logs directly from the runtime without submitting an operation. */
6226
6228
  post: operations["queryDockerProjectLogs"];
6227
6229
  delete?: never;
6228
6230
  options?: never;
@@ -6239,6 +6241,7 @@ export interface paths {
6239
6241
  };
6240
6242
  get?: never;
6241
6243
  put?: never;
6244
+ /** @description Requires docker.services.logs. The same permission is rechecked when opening the stream. */
6242
6245
  post: operations["issueDockerProjectLogStreamTicket"];
6243
6246
  delete?: never;
6244
6247
  options?: never;
@@ -7877,6 +7880,7 @@ export interface paths {
7877
7880
  };
7878
7881
  get?: never;
7879
7882
  put?: never;
7883
+ /** @description Enqueue a supported resource mutation. Container service actions are start, stop and restart. Log reads use the direct project log query API; action logs is rejected without creating a task. */
7880
7884
  post: operations["executeComputeResourceAction"];
7881
7885
  delete?: never;
7882
7886
  options?: never;
@@ -7974,6 +7978,7 @@ export interface paths {
7974
7978
  };
7975
7979
  get?: never;
7976
7980
  put?: never;
7981
+ /** @description Retry an asynchronous operation when its returned state permits it. Historical connection_test, port_reserve and service_action logs records remain readable but cannot be requeued; use their direct check, metadata or log query APIs instead. */
7977
7982
  post: operations["retryComputeTask"];
7978
7983
  delete?: never;
7979
7984
  options?: never;
@@ -12925,6 +12930,20 @@ export interface components {
12925
12930
  summary?: string;
12926
12931
  resources?: components["schemas"]["ComputeResourceRef"][];
12927
12932
  };
12933
+ /** @description Current connection health from a synchronous probe. This result is not a task and has no task identifier or lifecycle actions. */
12934
+ ConnectionCheckResult: {
12935
+ healthy: boolean;
12936
+ status: string;
12937
+ message?: string;
12938
+ reason?: string;
12939
+ nextAction?: string;
12940
+ httpStatus?: number;
12941
+ /** Format: date-time */
12942
+ checkedAt: string;
12943
+ };
12944
+ ConnectionCheckResultEnvelope: {
12945
+ data: components["schemas"]["ConnectionCheckResult"];
12946
+ };
12928
12947
  ComputeTaskView: {
12929
12948
  id: string;
12930
12949
  domain: components["schemas"]["ComputeTaskDomain"];
@@ -14173,6 +14192,10 @@ export interface components {
14173
14192
  loginLogoUrl: string;
14174
14193
  expandedLogoUrl: string;
14175
14194
  collapsedLogoUrl: string;
14195
+ /** @description Optional dark-theme expanded logo. Empty or absent uses expandedLogoUrl. */
14196
+ darkExpandedLogoUrl?: string;
14197
+ /** @description Optional dark-theme compact logo. Empty or absent uses collapsedLogoUrl. */
14198
+ darkCollapsedLogoUrl?: string;
14176
14199
  faviconUrl: string;
14177
14200
  };
14178
14201
  BrandingSettingsEnvelope: {
@@ -14185,6 +14208,10 @@ export interface components {
14185
14208
  loginLogoUrl: string;
14186
14209
  expandedLogoUrl: string;
14187
14210
  collapsedLogoUrl: string;
14211
+ /** @description Optional dark-theme expanded logo. Empty or absent clears the override. */
14212
+ darkExpandedLogoUrl?: string;
14213
+ /** @description Optional dark-theme compact logo. Empty or absent clears the override. */
14214
+ darkCollapsedLogoUrl?: string;
14188
14215
  faviconUrl: string;
14189
14216
  };
14190
14217
  BrandingAssetUpload: {
@@ -26364,6 +26391,8 @@ export type ComputeTaskResultStatus = components['schemas']['ComputeTaskResultSt
26364
26391
  export type ComputeTaskResult = components['schemas']['ComputeTaskResult'];
26365
26392
  export type ComputeTaskVerificationStatus = components['schemas']['ComputeTaskVerificationStatus'];
26366
26393
  export type ComputeTaskVerification = components['schemas']['ComputeTaskVerification'];
26394
+ export type ConnectionCheckResult = components['schemas']['ConnectionCheckResult'];
26395
+ export type ConnectionCheckResultEnvelope = components['schemas']['ConnectionCheckResultEnvelope'];
26367
26396
  export type ComputeTaskView = components['schemas']['ComputeTaskView'];
26368
26397
  export type ComputeTaskListEnvelope = components['schemas']['ComputeTaskListEnvelope'];
26369
26398
  export type ComputeTaskEnvelope = components['schemas']['ComputeTaskEnvelope'];
@@ -30247,6 +30276,7 @@ export interface operations {
30247
30276
  };
30248
30277
  403: components["responses"]["Error"];
30249
30278
  404: components["responses"]["Error"];
30279
+ 409: components["responses"]["Error"];
30250
30280
  };
30251
30281
  };
30252
30282
  getApplicationDeliveryDetail: {
@@ -34265,7 +34295,16 @@ export interface operations {
34265
34295
  };
34266
34296
  requestBody?: never;
34267
34297
  responses: {
34268
- /** @description Completed connection-test operation. */
34298
+ /** @description Completed synchronous connection check. Each request probes the connection and returns its current health; no task or task log is created. */
34299
+ 200: {
34300
+ headers: {
34301
+ [name: string]: unknown;
34302
+ };
34303
+ content: {
34304
+ "application/json": components["schemas"]["ConnectionCheckResultEnvelope"];
34305
+ };
34306
+ };
34307
+ /** @description Legacy response for a completed connection check, retained for older servers. Read the operation result directly. */
34269
34308
  202: {
34270
34309
  headers: {
34271
34310
  [name: string]: unknown;
@@ -43865,7 +43904,16 @@ export interface operations {
43865
43904
  };
43866
43905
  };
43867
43906
  responses: {
43868
- /** @description Health check accepted as a source-domain task. The request never returns the Provider raw response. */
43907
+ /** @description Completed synchronous health check. Each request probes the connection and returns its current health; no task or task log is created. Idempotency-Key is accepted for request compatibility but does not replay an earlier check. */
43908
+ 200: {
43909
+ headers: {
43910
+ [name: string]: unknown;
43911
+ };
43912
+ content: {
43913
+ "application/json": components["schemas"]["ConnectionCheckResultEnvelope"];
43914
+ };
43915
+ };
43916
+ /** @description Legacy health-check response retained for older servers. The task contains the completed result, never the Provider raw response. */
43869
43917
  202: {
43870
43918
  headers: {
43871
43919
  [name: string]: unknown;
@@ -44177,6 +44225,7 @@ export interface operations {
44177
44225
  "application/json": components["schemas"]["ComputeTaskEnvelope"];
44178
44226
  };
44179
44227
  };
44228
+ 400: components["responses"]["ComputeError"];
44180
44229
  403: components["responses"]["ComputeError"];
44181
44230
  404: components["responses"]["ComputeError"];
44182
44231
  409: components["responses"]["ComputeError"];
@@ -6981,6 +6981,14 @@
6981
6981
  "collapsedLogoUrl": {
6982
6982
  "type": "string"
6983
6983
  },
6984
+ "darkCollapsedLogoUrl": {
6985
+ "description": "Optional dark-theme compact logo. Empty or absent uses collapsedLogoUrl.",
6986
+ "type": "string"
6987
+ },
6988
+ "darkExpandedLogoUrl": {
6989
+ "description": "Optional dark-theme expanded logo. Empty or absent uses expandedLogoUrl.",
6990
+ "type": "string"
6991
+ },
6984
6992
  "expandedLogoUrl": {
6985
6993
  "type": "string"
6986
6994
  },
@@ -10967,6 +10975,52 @@
10967
10975
  ],
10968
10976
  "type": "object"
10969
10977
  },
10978
+ "ConnectionCheckResult": {
10979
+ "additionalProperties": false,
10980
+ "description": "Current connection health from a synchronous probe. This result is not a task and has no task identifier or lifecycle actions.",
10981
+ "properties": {
10982
+ "checkedAt": {
10983
+ "format": "date-time",
10984
+ "type": "string"
10985
+ },
10986
+ "healthy": {
10987
+ "type": "boolean"
10988
+ },
10989
+ "httpStatus": {
10990
+ "type": "integer"
10991
+ },
10992
+ "message": {
10993
+ "type": "string"
10994
+ },
10995
+ "nextAction": {
10996
+ "type": "string"
10997
+ },
10998
+ "reason": {
10999
+ "type": "string"
11000
+ },
11001
+ "status": {
11002
+ "type": "string"
11003
+ }
11004
+ },
11005
+ "required": [
11006
+ "healthy",
11007
+ "status",
11008
+ "checkedAt"
11009
+ ],
11010
+ "type": "object"
11011
+ },
11012
+ "ConnectionCheckResultEnvelope": {
11013
+ "additionalProperties": false,
11014
+ "properties": {
11015
+ "data": {
11016
+ "$ref": "#/components/schemas/ConnectionCheckResult"
11017
+ }
11018
+ },
11019
+ "required": [
11020
+ "data"
11021
+ ],
11022
+ "type": "object"
11023
+ },
10970
11024
  "CreatedPersonalAccessToken": {
10971
11025
  "additionalProperties": false,
10972
11026
  "properties": {
@@ -54718,6 +54772,14 @@
54718
54772
  "collapsedLogoUrl": {
54719
54773
  "type": "string"
54720
54774
  },
54775
+ "darkCollapsedLogoUrl": {
54776
+ "description": "Optional dark-theme compact logo. Empty or absent clears the override.",
54777
+ "type": "string"
54778
+ },
54779
+ "darkExpandedLogoUrl": {
54780
+ "description": "Optional dark-theme expanded logo. Empty or absent clears the override.",
54781
+ "type": "string"
54782
+ },
54721
54783
  "expandedLogoUrl": {
54722
54784
  "type": "string"
54723
54785
  },
@@ -60734,7 +60796,7 @@
60734
60796
  "info": {
60735
60797
  "description": "Public OpenSoha core API contract. This first contract focuses on stable cross-repository boundaries: auth, health, runner-facing control-plane callbacks, AI Gateway, and MCP capability discovery.\n",
60736
60798
  "title": "Soha API",
60737
- "version": "0.1.18"
60799
+ "version": "0.1.19"
60738
60800
  },
60739
60801
  "openapi": "3.1.0",
60740
60802
  "paths": {
@@ -68992,6 +69054,7 @@
68992
69054
  },
68993
69055
  "/applications/{applicationID}": {
68994
69056
  "delete": {
69057
+ "description": "Deletes the application and its owned configuration and history. Does not uninstall cluster workloads. Unfinished delivery tasks or external references prevent deletion.",
68995
69058
  "operationId": "deleteApplication",
68996
69059
  "parameters": [
68997
69060
  {
@@ -69014,6 +69077,9 @@
69014
69077
  },
69015
69078
  "404": {
69016
69079
  "$ref": "#/components/responses/Error"
69080
+ },
69081
+ "409": {
69082
+ "$ref": "#/components/responses/Error"
69017
69083
  }
69018
69084
  },
69019
69085
  "tags": [
@@ -77566,6 +77632,16 @@
77566
77632
  "required": true
77567
77633
  },
77568
77634
  "responses": {
77635
+ "200": {
77636
+ "content": {
77637
+ "application/json": {
77638
+ "schema": {
77639
+ "$ref": "#/components/schemas/ConnectionCheckResultEnvelope"
77640
+ }
77641
+ }
77642
+ },
77643
+ "description": "Completed synchronous health check. Each request probes the connection and returns its current health; no task or task log is created. Idempotency-Key is accepted for request compatibility but does not replay an earlier check."
77644
+ },
77569
77645
  "202": {
77570
77646
  "content": {
77571
77647
  "application/json": {
@@ -77574,7 +77650,7 @@
77574
77650
  }
77575
77651
  }
77576
77652
  },
77577
- "description": "Health check accepted as a source-domain task. The request never returns the Provider raw response."
77653
+ "description": "Legacy health-check response retained for older servers. The task contains the completed result, never the Provider raw response."
77578
77654
  },
77579
77655
  "400": {
77580
77656
  "$ref": "#/components/responses/ComputeError"
@@ -77683,6 +77759,7 @@
77683
77759
  },
77684
77760
  "/compute/resources/{domain}/{kind}/{id}/actions/{action}": {
77685
77761
  "post": {
77762
+ "description": "Enqueue a supported resource mutation. Container service actions are start, stop and restart. Log reads use the direct project log query API; action logs is rejected without creating a task.",
77686
77763
  "operationId": "executeComputeResourceAction",
77687
77764
  "parameters": [
77688
77765
  {
@@ -78013,6 +78090,7 @@
78013
78090
  },
78014
78091
  "/compute/tasks/{domain}/{id}/retry": {
78015
78092
  "post": {
78093
+ "description": "Retry an asynchronous operation when its returned state permits it. Historical connection_test, port_reserve and service_action logs records remain readable but cannot be requeued; use their direct check, metadata or log query APIs instead.",
78016
78094
  "operationId": "retryComputeTask",
78017
78095
  "parameters": [
78018
78096
  {
@@ -78046,6 +78124,9 @@
78046
78124
  },
78047
78125
  "description": "Retry delegated to the source domain and returned as a new task with a new immutable Provider snapshot."
78048
78126
  },
78127
+ "400": {
78128
+ "$ref": "#/components/responses/ComputeError"
78129
+ },
78049
78130
  "403": {
78050
78131
  "$ref": "#/components/responses/ComputeError"
78051
78132
  },
@@ -84739,6 +84820,7 @@
84739
84820
  },
84740
84821
  "/docker/projects/{dockerProjectID}/logs/query": {
84741
84822
  "post": {
84823
+ "description": "Requires docker.services.logs. Reads bounded logs directly from the runtime without submitting an operation.",
84742
84824
  "operationId": "queryDockerProjectLogs",
84743
84825
  "parameters": [
84744
84826
  {
@@ -84789,6 +84871,7 @@
84789
84871
  },
84790
84872
  "/docker/projects/{dockerProjectID}/logs/stream-ticket": {
84791
84873
  "post": {
84874
+ "description": "Requires docker.services.logs. The same permission is rechecked when opening the stream.",
84792
84875
  "operationId": "issueDockerProjectLogStreamTicket",
84793
84876
  "parameters": [
84794
84877
  {
@@ -96185,6 +96268,16 @@
96185
96268
  }
96186
96269
  ],
96187
96270
  "responses": {
96271
+ "200": {
96272
+ "content": {
96273
+ "application/json": {
96274
+ "schema": {
96275
+ "$ref": "#/components/schemas/ConnectionCheckResultEnvelope"
96276
+ }
96277
+ }
96278
+ },
96279
+ "description": "Completed synchronous connection check. Each request probes the connection and returns its current health; no task or task log is created."
96280
+ },
96188
96281
  "202": {
96189
96282
  "content": {
96190
96283
  "application/json": {
@@ -96193,7 +96286,7 @@
96193
96286
  }
96194
96287
  }
96195
96288
  },
96196
- "description": "Completed connection-test operation."
96289
+ "description": "Legacy response for a completed connection check, retained for older servers. Read the operation result directly."
96197
96290
  },
96198
96291
  "403": {
96199
96292
  "$ref": "#/components/responses/Error"
@@ -1,7 +1,7 @@
1
1
  openapi: 3.1.0
2
2
  info:
3
3
  title: Soha API
4
- version: 0.1.18
4
+ version: 0.1.19
5
5
  description: >
6
6
  Public OpenSoha core API contract. This first contract focuses on stable
7
7
  cross-repository boundaries: auth, health, runner-facing control-plane
@@ -2163,6 +2163,7 @@ paths:
2163
2163
  delete:
2164
2164
  tags: [Applications]
2165
2165
  operationId: deleteApplication
2166
+ description: Deletes the application and its owned configuration and history. Does not uninstall cluster workloads. Unfinished delivery tasks or external references prevent deletion.
2166
2167
  parameters:
2167
2168
  - $ref: "#/components/parameters/ApplicationID"
2168
2169
  responses:
@@ -2176,6 +2177,8 @@ paths:
2176
2177
  $ref: "#/components/responses/Error"
2177
2178
  "404":
2178
2179
  $ref: "#/components/responses/Error"
2180
+ "409":
2181
+ $ref: "#/components/responses/Error"
2179
2182
  /applications/{applicationID}/detail:
2180
2183
  get:
2181
2184
  tags: [Applications, Delivery]
@@ -5456,8 +5459,13 @@ paths:
5456
5459
  parameters:
5457
5460
  - { name: connectionID, in: path, required: true, schema: { type: string } }
5458
5461
  responses:
5462
+ "200":
5463
+ description: Completed synchronous connection check. Each request probes the connection and returns its current health; no task or task log is created.
5464
+ content:
5465
+ application/json:
5466
+ schema: { $ref: "#/components/schemas/ConnectionCheckResultEnvelope" }
5459
5467
  "202":
5460
- description: Completed connection-test operation.
5468
+ description: Legacy response for a completed connection check, retained for older servers. Read the operation result directly.
5461
5469
  content:
5462
5470
  application/json:
5463
5471
  schema: { $ref: "#/components/schemas/VirtualizationOperationEnvelope" }
@@ -10296,6 +10304,7 @@ paths:
10296
10304
  post:
10297
10305
  tags: [Docker]
10298
10306
  operationId: queryDockerProjectLogs
10307
+ description: Requires docker.services.logs. Reads bounded logs directly from the runtime without submitting an operation.
10299
10308
  parameters:
10300
10309
  - $ref: "#/components/parameters/DockerProjectID"
10301
10310
  requestBody:
@@ -10325,6 +10334,7 @@ paths:
10325
10334
  post:
10326
10335
  tags: [Docker]
10327
10336
  operationId: issueDockerProjectLogStreamTicket
10337
+ description: Requires docker.services.logs. The same permission is rechecked when opening the stream.
10328
10338
  parameters:
10329
10339
  - $ref: "#/components/parameters/DockerProjectID"
10330
10340
  requestBody:
@@ -13681,8 +13691,14 @@ paths:
13681
13691
  schema:
13682
13692
  $ref: "#/components/schemas/ComputeProviderReadRequest"
13683
13693
  responses:
13694
+ "200":
13695
+ description: Completed synchronous health check. Each request probes the connection and returns its current health; no task or task log is created. Idempotency-Key is accepted for request compatibility but does not replay an earlier check.
13696
+ content:
13697
+ application/json:
13698
+ schema:
13699
+ $ref: "#/components/schemas/ConnectionCheckResultEnvelope"
13684
13700
  "202":
13685
- description: Health check accepted as a source-domain task. The request never returns the Provider raw response.
13701
+ description: Legacy health-check response retained for older servers. The task contains the completed result, never the Provider raw response.
13686
13702
  content:
13687
13703
  application/json:
13688
13704
  schema:
@@ -13773,6 +13789,10 @@ paths:
13773
13789
  post:
13774
13790
  tags: [Compute]
13775
13791
  operationId: executeComputeResourceAction
13792
+ description: >-
13793
+ Enqueue a supported resource mutation. Container service actions are start,
13794
+ stop and restart. Log reads use the direct project log query API; action
13795
+ logs is rejected without creating a task.
13776
13796
  parameters:
13777
13797
  - $ref: "#/components/parameters/ComputeDomain"
13778
13798
  - $ref: "#/components/parameters/ComputeResourceKind"
@@ -13952,6 +13972,11 @@ paths:
13952
13972
  post:
13953
13973
  tags: [Compute]
13954
13974
  operationId: retryComputeTask
13975
+ description: >-
13976
+ Retry an asynchronous operation when its returned state permits it.
13977
+ Historical connection_test, port_reserve and service_action logs records
13978
+ remain readable but cannot be requeued; use their direct check, metadata
13979
+ or log query APIs instead.
13955
13980
  parameters:
13956
13981
  - $ref: "#/components/parameters/ComputeTaskDomain"
13957
13982
  - $ref: "#/components/parameters/ComputeTaskID"
@@ -13969,6 +13994,8 @@ paths:
13969
13994
  application/json:
13970
13995
  schema:
13971
13996
  $ref: "#/components/schemas/ComputeTaskEnvelope"
13997
+ "400":
13998
+ $ref: "#/components/responses/ComputeError"
13972
13999
  "403":
13973
14000
  $ref: "#/components/responses/ComputeError"
13974
14001
  "404":
@@ -23379,6 +23406,25 @@ components:
23379
23406
  type: array
23380
23407
  items: { $ref: "#/components/schemas/ComputeResourceRef" }
23381
23408
  additionalProperties: false
23409
+ ConnectionCheckResult:
23410
+ type: object
23411
+ description: Current connection health from a synchronous probe. This result is not a task and has no task identifier or lifecycle actions.
23412
+ required: [healthy, status, checkedAt]
23413
+ properties:
23414
+ healthy: { type: boolean }
23415
+ status: { type: string }
23416
+ message: { type: string }
23417
+ reason: { type: string }
23418
+ nextAction: { type: string }
23419
+ httpStatus: { type: integer }
23420
+ checkedAt: { type: string, format: date-time }
23421
+ additionalProperties: false
23422
+ ConnectionCheckResultEnvelope:
23423
+ type: object
23424
+ required: [data]
23425
+ properties:
23426
+ data: { $ref: "#/components/schemas/ConnectionCheckResult" }
23427
+ additionalProperties: false
23382
23428
  ComputeTaskView:
23383
23429
  type: object
23384
23430
  required: [id, domain, sourceType, sourceId, kind, category, normalizedStatus, rawStatus, resources, attemptCount, cancelable, retryable, availableActions, createdAt]
@@ -25309,6 +25355,12 @@ components:
25309
25355
  loginLogoUrl: { type: string }
25310
25356
  expandedLogoUrl: { type: string }
25311
25357
  collapsedLogoUrl: { type: string }
25358
+ darkExpandedLogoUrl:
25359
+ type: string
25360
+ description: Optional dark-theme expanded logo. Empty or absent uses expandedLogoUrl.
25361
+ darkCollapsedLogoUrl:
25362
+ type: string
25363
+ description: Optional dark-theme compact logo. Empty or absent uses collapsedLogoUrl.
25312
25364
  faviconUrl: { type: string }
25313
25365
  additionalProperties: false
25314
25366
  BrandingSettingsEnvelope:
@@ -25328,6 +25380,12 @@ components:
25328
25380
  loginLogoUrl: { type: string }
25329
25381
  expandedLogoUrl: { type: string }
25330
25382
  collapsedLogoUrl: { type: string }
25383
+ darkExpandedLogoUrl:
25384
+ type: string
25385
+ description: Optional dark-theme expanded logo. Empty or absent clears the override.
25386
+ darkCollapsedLogoUrl:
25387
+ type: string
25388
+ description: Optional dark-theme compact logo. Empty or absent clears the override.
25331
25389
  faviconUrl: { type: string }
25332
25390
  additionalProperties: false
25333
25391
  BrandingAssetUpload:
@@ -5,9 +5,9 @@ package openapi
5
5
  import _ "embed"
6
6
 
7
7
  const (
8
- Version = "0.1.18"
9
- YAMLSHA256 = "d614ce858924d94da353c7a9380971a3e80964f3e6c865e8b27108e859500cf4"
10
- JSONSHA256 = "a98ea9ad99b6f044ce14e42f37b90b42e28347d53e37c727a04210b076aba960"
8
+ Version = "0.1.19"
9
+ YAMLSHA256 = "a1edda91ecc623423ca1875777dd500f12f239ca1571d7276a23d5e6c00c4c40"
10
+ JSONSHA256 = "40f61307c9379b1496b43ff31fe8aebd82f1353100fe799f6d1ebbaefb1c3cd3"
11
11
  )
12
12
 
13
13
  //go:embed soha-api.yaml
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensoha/contracts",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "private": false,
5
5
  "description": "Shared OpenSoha API, agent, MCP, skill, event, and auth contracts.",
6
6
  "license": "Apache-2.0",