瀏覽代碼

docs: address CodeRabbit review on release PR #1157 (#1158)

James Read 17 小時之前
父節點
當前提交
a99e6981f7

+ 2 - 2
docs/modules/ROOT/nav.adoc

@@ -182,8 +182,8 @@
 * xref:api/intro.adoc[API]
 * xref:api/intro.adoc[API]
 ** xref:api/start_action.adoc[Start Actions from the API]
 ** xref:api/start_action.adoc[Start Actions from the API]
 *** xref:api/method_StartAction.adoc[StartAction]
 *** xref:api/method_StartAction.adoc[StartAction]
-*** xref:api/method_StartActionByGet.adoc[StartActionByGet]
 *** xref:api/method_StartActionAndWait.adoc[StartActionAndWait]
 *** xref:api/method_StartActionAndWait.adoc[StartActionAndWait]
-*** xref:api/method_StartActionByGetAndWait.adoc[StartActionByGetAndWait]
+*** xref:api/method_StartActionByGet.adoc[StartActionByGet (deprecated)]
+*** xref:api/method_StartActionByGetAndWait.adoc[StartActionByGetAndWait (deprecated)]
 ** xref:api/misc.adoc[Misc API calls]
 ** xref:api/misc.adoc[Misc API calls]
 ** xref:api/login.adoc[Local user login via the API]
 ** xref:api/login.adoc[Local user login via the API]

+ 3 - 3
docs/modules/ROOT/pages/api/intro.adoc

@@ -18,9 +18,9 @@ The API is exposed at `/api/` on the single HTTP frontend (port 1337 by default)
 The OliveTin API is completely machine readable - every method, request and response message, field, and enum is defined in the Protobuf files. This makes it straightforward for code generators, API tooling, and LLMs / AI agents to discover and use the API without guessing.
 The OliveTin API is completely machine readable - every method, request and response message, field, and enum is defined in the Protobuf files. This makes it straightforward for code generators, API tooling, and LLMs / AI agents to discover and use the API without guessing.
 
 
 * **Source of truth**: link:https://github.com/OliveTin/OliveTin/tree/main/proto[`proto/`] on GitHub - the service is `olivetin.api.v1.OliveTinApiService` in link:https://github.com/OliveTin/OliveTin/blob/main/proto/olivetin/api/v1/olivetin.proto[`olivetin/api/v1/olivetin.proto`].
 * **Source of truth**: link:https://github.com/OliveTin/OliveTin/tree/main/proto[`proto/`] on GitHub - the service is `olivetin.api.v1.OliveTinApiService` in link:https://github.com/OliveTin/OliveTin/blob/main/proto/olivetin/api/v1/olivetin.proto[`olivetin/api/v1/olivetin.proto`].
-* **Generate a client**: use link:https://buf.build[buf] or `protoc` with the Connect, gRPC, or gRPC-Web plugins for your language of choice (Go, TypeScript, Python, Java, etc).
-* **Call it directly**: each RPC is available as `POST /api/<MethodName>` with a JSON body matching the request message, using protobuf JSON field names (lowerCamelCase, eg: `bindingId`).
-* **HTTP method**: every RPC is called with `POST` - a `GET` request returns `405 Method Not Allowed`.
+* **Generate a client**: use link:https://buf.build[buf] or `protoc` with the Connect, gRPC, or gRPC-Web plugins for your language of choice (Go, TypeScript, Python, Java, etc). Set the client's base URL to `http://olivetinServer:1337/api` (not the server root) - the API is only served under `/api/`, and requests to `/olivetin.api.v1.OliveTinApiService/<MethodName>` at the root go to the web UI instead.
+* **Call it directly**: each unary RPC is available as `POST /api/<MethodName>` with a JSON body matching the request message, using protobuf JSON field names (lowerCamelCase, eg: `bindingId`). Server-streaming RPCs (`EventStream`) use the Connect streaming protocol (enveloped `application/connect+json` messages), so they cannot be called with a plain JSON request - use a generated Connect client for those.
+* **HTTP method**: every unary RPC is called with `POST` - a `GET` request returns `405 Method Not Allowed`.
 * **OpenAPI**: the Swagger / OpenAPI links below are generated from the Protobuf files, and are also available for tools that prefer OpenAPI.
 * **OpenAPI**: the Swagger / OpenAPI links below are generated from the Protobuf files, and are also available for tools that prefer OpenAPI.
 
 
 == Links
 == Links

+ 11 - 23
docs/modules/ROOT/pages/api/method_StartActionByGet.adoc

@@ -1,35 +1,23 @@
-= API Method: StartActionByGet
+= API Method: StartActionByGet (deprecated)
 
 
-This is the simplest method to start an action - you only need to send the action ID, which makes it a good fit for quick integrations (Stream Deck, Home Assistant, cron jobs, etc). You cannot pass arguments using this method.
-
-* **HTTP Method**: `POST`
-* **Request Type**: xref:api/start_action.adoc#api-request-actionid[Action ID only] (`actionId`)
-* **Response Type**: Execution Tracking ID
-
-[NOTE]
+[WARNING]
 ====
 ====
-Despite the name, in OliveTin 3k this method is called with `POST` and a JSON body, the same as every other API method. The OliveTin 2k style of putting the action ID in the URL (eg: `GET /api/StartActionByGet/pingGithub`) is no longer supported and returns `404`.
+`StartActionByGet` is **deprecated** and will be removed in a future version of OliveTin. Use xref:api/method_StartAction.adoc[StartAction] instead.
+
+Despite its name, this method no longer supports `GET` requests. The OliveTin 2k style of putting the action ID in the URL (eg: `GET /api/StartActionByGet/pingGithub`) returns `404` in OliveTin 3k, and is not coming back.
 ====
 ====
 
 
-include::partial$api/start_action_methods.adoc[]
+== Migrating to `StartAction`
 
 
-[#api-eg-startActionId]
-== Example API call: Start an action by ID
+`StartActionByGet` takes only an `actionId`, and returns an Execution Tracking ID. `StartAction` does the same with `bindingId` - for a normal action, the binding ID is the same as the action `id` from your `config.yaml` (see xref:api/start_action.adoc#api-ids[Action IDs vs Binding IDs]).
 
 
-.curl
+.Before (deprecated)
 ----
 ----
 user@host: curl http://olivetin.example.com:1337/api/StartActionByGet --json '{"actionId": "pingGithub"}'
 user@host: curl http://olivetin.example.com:1337/api/StartActionByGet --json '{"actionId": "pingGithub"}'
-{"executionTrackingId":"ff7d6f13-af8f-4ebe-8174-ad4cc7197b45"}
 ----
 ----
 
 
-The corresponding config.yaml would look like this;
-
-[source,yaml]
+.After
 ----
 ----
-actions:
-  - title: Ping GitHub.com
-    id: pingGithub
-    shell: ping github.com -c 1
+user@host: curl http://olivetin.example.com:1337/api/StartAction --json '{"bindingId": "pingGithub"}'
+{"executionTrackingId":"ff7d6f13-af8f-4ebe-8174-ad4cc7197b45"}
 ----
 ----
-
-IDs are used by these API calls, as you probably want the interface to display a human-readable title, whereas the API call doesn't want to have spaces or punctuation.

+ 13 - 16
docs/modules/ROOT/pages/api/method_StartActionByGetAndWait.adoc

@@ -1,26 +1,23 @@
-= API Method: StartActionByGetAndWait
+= API Method: StartActionByGetAndWait (deprecated)
 
 
-This method is also a very easy way to quickly start an action, but it waits for the action to finish before returning the result. This is useful if you want to get the output of the action or check its result without having to poll for it. You cannot pass arguments using this method.
-
-* **HTTP Method**: `POST`
-* **Request Type**: xref:api/start_action.adoc#api-request-actionid[Action ID only] (`actionId`)
-* **Response Type**: Log Entry (waits for the action to finish)
-
-[NOTE]
-====
-Despite the name, in OliveTin 3k this method is called with `POST` and a JSON body. The OliveTin 2k style of putting the action ID in the URL (eg: `GET /api/StartActionByGetAndWait/pingGithub`) is no longer supported and returns `404`.
+[WARNING]
 ====
 ====
+`StartActionByGetAndWait` is **deprecated** and will be removed in a future version of OliveTin. Use xref:api/method_StartActionAndWait.adoc[StartActionAndWait] instead.
 
 
-There are several variants of this API call available which might be easier for scripts (or humans) to work with:
+Despite its name, this method no longer supports `GET` requests. The OliveTin 2k style of putting the action ID in the URL (eg: `GET /api/StartActionByGetAndWait/pingGithub`) returns `404` in OliveTin 3k, and is not coming back.
+====
 
 
-include::partial$api/start_action_methods.adoc[]
+== Migrating to `StartActionAndWait`
 
 
-== Example API call: Start an action by ID, and wait for it to finish
+`StartActionAndWait` takes the same `actionId` field, and returns the same Log Entry, so you only need to change the method name. It also accepts `arguments` and a `justification`.
 
 
-.curl
+.Before (deprecated)
 ----
 ----
 user@host: curl http://olivetin.example.com:1337/api/StartActionByGetAndWait --json '{"actionId": "pingGithub"}'
 user@host: curl http://olivetin.example.com:1337/api/StartActionByGetAndWait --json '{"actionId": "pingGithub"}'
-{"logEntry":{"actionTitle":"Ping GitHub.com","output":"...","exitCode":0, ... }}
 ----
 ----
 
 
-See xref:api/start_action.adoc#api-response-logentry[Response type: LogEntry] for the full response.
+.After
+----
+user@host: curl http://olivetin.example.com:1337/api/StartActionAndWait --json '{"actionId": "pingGithub"}'
+{"logEntry":{"actionTitle":"Ping GitHub.com","output":"...","exitCode":0, ... }}
+----

+ 22 - 24
docs/modules/ROOT/pages/api/start_action.adoc

@@ -1,7 +1,7 @@
 [#api-start-action]
 [#api-start-action]
 = Starting Actions from the API
 = Starting Actions from the API
 
 
-There are several variants of this API call available which might be easier for scripts (or humans) to work with!
+There are two API methods for starting actions: `StartAction`, which returns straight away, and `StartActionAndWait`, which waits for the action to finish.
 
 
 include::partial$api/start_action_methods.adoc[]
 include::partial$api/start_action_methods.adoc[]
 
 
@@ -13,27 +13,7 @@ All request and response field names below are the protobuf JSON names (lowerCam
 * `actionId` is the `id` you set on the action in your `config.yaml`. To find your Action ID, and understand how Action IDs work, see the xref:action_customization/ids.adoc[Action ID] documentation.
 * `actionId` is the `id` you set on the action in your `config.yaml`. To find your Action ID, and understand how Action IDs work, see the xref:action_customization/ids.adoc[Action ID] documentation.
 * `bindingId` identifies one button/instance of an action. For a normal action this is the same as the action ID. For actions generated from xref:entities/intro.adoc[entities], each entity gets its own binding ID. Binding IDs are returned by `GetDashboard` (as `action.bindingId`).
 * `bindingId` identifies one button/instance of an action. For a normal action this is the same as the action ID. For actions generated from xref:entities/intro.adoc[entities], each entity gets its own binding ID. Binding IDs are returned by `GetDashboard` (as `action.bindingId`).
 
 
-NOTE: Despite its name, the `actionId` field used by `StartActionAndWait`, `StartActionByGet` and `StartActionByGetAndWait` is looked up as a binding ID. For normal actions this makes no difference, but for entity-generated actions you must send the entity's binding ID - sending the configured action `id` returns `not_found`.
-
-[#api-request-actionid]
-== Request type: Action ID only
-
-Used by:
-
-*** xref:api/method_StartActionByGet.adoc[StartActionByGet]
-*** xref:api/method_StartActionByGetAndWait.adoc[StartActionByGetAndWait]
-
-If you are trying to integrate OliveTin with your own scripts or processes, this is probably the easiest way to start actions. You cannot pass arguments with this request type.
-
-[source,json]
-.`StartActionByGetRequest` / `StartActionByGetAndWaitRequest`
-----
-{
-  "actionId": "string"
-}
-----
-
-See xref:api/method_StartActionByGet.adoc#api-eg-startActionId[the example].
+NOTE: Despite its name, the `actionId` field used by `StartActionAndWait` is looked up as a binding ID. For normal actions this makes no difference, but for entity-generated actions you must send the entity's binding ID - sending the configured action `id` returns `not_found`.
 
 
 [#api-request-startaction]
 [#api-request-startaction]
 == Request type: StartAction request object
 == Request type: StartAction request object
@@ -105,7 +85,6 @@ Note that this request selects the action with `actionId` (not `bindingId`), and
 Used by:
 Used by:
 
 
 *** xref:api/method_StartAction.adoc[StartAction]
 *** xref:api/method_StartAction.adoc[StartAction]
-*** xref:api/method_StartActionByGet.adoc[StartActionByGet]
 
 
 .Example Execution Tracking ID response
 .Example Execution Tracking ID response
 [source,json]
 [source,json]
@@ -119,7 +98,6 @@ Used by:
 Used by:
 Used by:
 
 
 *** xref:api/method_StartActionAndWait.adoc[StartActionAndWait]
 *** xref:api/method_StartActionAndWait.adoc[StartActionAndWait]
-*** xref:api/method_StartActionByGetAndWait.adoc[StartActionByGetAndWait]
 
 
 The `output` field contains the combined stdout and stderr of the action.
 The `output` field contains the combined stdout and stderr of the action.
 
 
@@ -158,3 +136,23 @@ The `output` field contains the combined stdout and stderr of the action.
   }
   }
 }
 }
 ----
 ----
+
+[#api-deprecated-byget]
+== Deprecated: StartActionByGet and StartActionByGetAndWait
+
+`StartActionByGet` and `StartActionByGetAndWait` are deprecated, and will be removed in a future version of OliveTin. They only accept an `actionId` (no arguments), and despite their names they no longer support `GET` requests - the OliveTin 2k style of putting the action ID in the URL returns `404`.
+
+When either method is called, OliveTin shows a warning on the xref:advanced_configuration/diagnostics.adoc[Diagnostics] page (code `deprecated_api_call`), so you can find integrations that still need updating. The warning is cleared when OliveTin restarts.
+
+[%header]
+|===
+| Deprecated method | Use instead | Change
+
+| xref:api/method_StartActionByGet.adoc[StartActionByGet]
+| xref:api/method_StartAction.adoc[StartAction]
+| Send `{"bindingId": "..."}` instead of `{"actionId": "..."}`
+
+| xref:api/method_StartActionByGetAndWait.adoc[StartActionByGetAndWait]
+| xref:api/method_StartActionAndWait.adoc[StartActionAndWait]
+| Change the method name only - the request is the same
+|===

+ 10 - 0
docs/modules/ROOT/pages/install/podmandocker.adoc

@@ -29,4 +29,14 @@ OliveTin does not need to be run as a root, and does not need any special capabi
 
 
 To change the xref:advanced_configuration/timezones.adoc[changing the timezone requires a bound-mount] from the host. Olivetin ignores the TZ variable as it is non-standard.
 To change the xref:advanced_configuration/timezones.adoc[changing the timezone requires a bound-mount] from the host. Olivetin ignores the TZ variable as it is non-standard.
 
 
+[#container-healthcheck]
+== Container healthcheck
+
+The OliveTin container image includes a Docker `HEALTHCHECK` that requests `http://127.0.0.1:$PORT/readyz` inside the container, with `PORT` defaulting to `1337`. The healthcheck cannot read your `config.yaml`, so if you change the port with `listenAddressSingleHTTPFrontend`, either:
+
+* set the xref:reference/network-ports.adoc[`PORT` environment variable] to the same port (`PORT` also overrides the port in `config.yaml`, so the two always match), or
+* override the healthcheck in your deployment (eg: `--health-cmd` with `docker run`, or `healthcheck:` in Docker Compose).
+
+Otherwise the container is reported as `unhealthy`, even though OliveTin is running normally.
+
 include::partial$install/post_container.adoc[]
 include::partial$install/post_container.adoc[]

+ 12 - 4
docs/modules/ROOT/pages/integrations/homeassistant.adoc

@@ -19,9 +19,17 @@ actions:
     shell: ssh user@server "sudo systemctl suspend"
     shell: ssh user@server "sudo systemctl suspend"
 ----
 ----
 
 
-You then need to know the URL to call to trigger this action. This is the OliveTin API URL plus the method name, and the action ID is sent in a JSON body. For example, if your OliveTin is running at `http://yourserver:1337`, you would `POST` `{"actionId": "server_sleep"}` to `http://yourserver:1337/api/StartActionByGetAndWait`.
+You then need to know the URL to call to trigger this action. This is the OliveTin API URL plus the method name, and the action is selected in a JSON body. For example, if your OliveTin is running at `http://yourserver:1337`, you would `POST` `{"bindingId": "server_sleep"}` to `http://yourserver:1337/api/StartAction`. (For a normal action, the `bindingId` is the same as the action `id`.)
 
 
-You can learn more about starting actions via the OliveTin API by reading the link xref:api/start_action.adoc[Starting Actions via the API] page, but the method "StartActionByGetAndWait" is the one you will want to use for Home Assistant.
+You can learn more about starting actions via the OliveTin API by reading the link xref:api/start_action.adoc[Starting Actions via the API] page, but the method "StartAction" is the one you will want to use for Home Assistant. It returns as soon as the action has started.
+
+[NOTE]
+====
+Avoid `StartActionAndWait` for Home Assistant unless you need the action's output:
+
+* It only responds once the action has finished, and Home Assistant's `rest_command` gives up after 10 seconds by default, so longer actions are reported as failed even though they ran.
+* It checks that the caller can view the action's logs *after* the action has run. Without the `logs` permission, Home Assistant gets an error even though the action ran, and retrying runs it again.
+====
 
 
 == Add the REST API call to Home Assistant
 == Add the REST API call to Home Assistant
 
 
@@ -45,10 +53,10 @@ From the file editor now in your sidebar, browse the filesystem to the configura
 ----
 ----
 rest_command:
 rest_command:
   olivetin_sleep_mindstorm:
   olivetin_sleep_mindstorm:
-    url: http://olivetin.example.com:1337/api/StartActionByGetAndWait
+    url: http://olivetin.example.com:1337/api/StartAction
     method: post
     method: post
     content_type: "application/json"
     content_type: "application/json"
-    payload: '{"actionId": "server_sleep"}'
+    payload: '{"bindingId": "server_sleep"}'
 ----
 ----
 
 
 You save the file, and restart Home Assistant to pick up the changes.
 You save the file, and restart Home Assistant to pick up the changes.

+ 2 - 0
docs/modules/ROOT/pages/reference/network-ports.adoc

@@ -57,6 +57,8 @@ If the `PORT` environment variable is set at startup, OliveTin uses it as the li
 
 
 When `PORT` is not set, OliveTin uses `listenAddressSingleHTTPFrontend` from the config, or `0.0.0.0:1337` if that setting is omitted.
 When `PORT` is not set, OliveTin uses `listenAddressSingleHTTPFrontend` from the config, or `0.0.0.0:1337` if that setting is omitted.
 
 
+The container image's healthcheck also uses `PORT` (default `1337`), so if you run the container on a different port, see xref:install/podmandocker.adoc#container-healthcheck[Container healthcheck].
+
 == See also
 == See also
 
 
 * xref:reference/multiple_instances[Running Multiple instances of OliveTin on the same server]
 * xref:reference/multiple_instances[Running Multiple instances of OliveTin on the same server]

+ 9 - 0
docs/modules/ROOT/pages/security/oauth2_pocketid.adoc

@@ -73,12 +73,21 @@ defaultPermissions:
   exec: false
   exec: false
   logs: false
   logs: false
 
 
+# showDiagnostics and showLogList default to true for everyone (including
+# guests), so turn them off here and enable them for admins only below.
+defaultPolicy:
+  showDiagnostics: false
+  showLogList: false
+
 accessControlLists:
 accessControlLists:
   - name: admin
   - name: admin
     permissions:
     permissions:
       view: true
       view: true
       exec: true
       exec: true
       logs: true
       logs: true
+    policy:
+      showDiagnostics: true
+      showLogList: true
     matchUsergroups:
     matchUsergroups:
       - olivetin_admin
       - olivetin_admin
     addToEveryAction: true
     addToEveryAction: true

+ 4 - 12
docs/modules/ROOT/partials/api/start_action_methods.adoc

@@ -1,4 +1,4 @@
-There are 4 main methods to start an action in OliveTin, which can be used in scripts or other applications. These methods allow you to trigger actions either immediately or wait for them to complete. Like every OliveTin API method, they are called with an HTTP `POST` and a JSON request body (eg: `curl --json '{...}'`).
+There are 2 methods to start an action in OliveTin, which can be used in scripts or other applications. These methods allow you to trigger actions either immediately or wait for them to complete. Like every OliveTin API method, they are called with an HTTP `POST` and a JSON request body (eg: `curl --json '{...}'`).
 
 
 .Webhook/API reference table
 .Webhook/API reference table
 [%header]
 [%header]
@@ -10,23 +10,15 @@ There are 4 main methods to start an action in OliveTin, which can be used in sc
 | xref:api/start_action.adoc#api-request-startaction[`bindingId`, arguments, tracking ID, justification]
 | xref:api/start_action.adoc#api-request-startaction[`bindingId`, arguments, tracking ID, justification]
 | xref:api/start_action.adoc#api-response-trackingid[Execution Tracking ID]
 | xref:api/start_action.adoc#api-response-trackingid[Execution Tracking ID]
 
 
-| xref:api/method_StartActionByGet.adoc[StartActionByGet]
-| POST
-| xref:api/start_action.adoc#api-request-actionid[`actionId` only]
-| xref:api/start_action.adoc#api-response-trackingid[Execution Tracking ID]
-
 | xref:api/method_StartActionAndWait.adoc[StartActionAndWait]
 | xref:api/method_StartActionAndWait.adoc[StartActionAndWait]
 | POST
 | POST
 | xref:api/start_action.adoc#api-request-startactionandwait[`actionId`, arguments, justification]
 | xref:api/start_action.adoc#api-request-startactionandwait[`actionId`, arguments, justification]
 | xref:api/start_action.adoc#api-response-logentry[Log Entry (waits for the action to finish)]
 | xref:api/start_action.adoc#api-response-logentry[Log Entry (waits for the action to finish)]
 
 
-| xref:api/method_StartActionByGetAndWait.adoc[StartActionByGetAndWait]
-| POST
-| xref:api/start_action.adoc#api-request-actionid[`actionId` only]
-| xref:api/start_action.adoc#api-response-logentry[Log Entry (waits for the action to finish)]
-
 |======================================================
 |======================================================
 
 
-NOTE: The waiting methods (`StartActionAndWait` and `StartActionByGetAndWait`) check that the caller is allowed to view the action's logs *after* the action has finished. A caller that can start an action but cannot view its logs receives a permission error, even though the action has already run - so retrying on that error can run the action again. Use `StartAction` or `StartActionByGet` when you do not need the log entry.
+NOTE: `StartActionAndWait` checks that the caller is allowed to view the action's logs *after* the action has finished. A caller that can start an action but cannot view its logs receives a permission error, even though the action has already run - so retrying on that error can run the action again. Use `StartAction` when you do not need the log entry.
+
+WARNING: `StartActionByGet` and `StartActionByGetAndWait` are xref:api/start_action.adoc#api-deprecated-byget[deprecated] and will be removed in a future version. Use `StartAction` or `StartActionAndWait` instead.
 
 
 You can also browse these methods in the link:https://docs.olivetin.app/api/swagger/3k/[OpenAPI/Swagger] docs if you prefer. The link:https://github.com/OliveTin/OliveTin/blob/main/proto/olivetin/api/v1/olivetin.proto[Protobuf definition] is the source of truth for all request and response fields.
 You can also browse these methods in the link:https://docs.olivetin.app/api/swagger/3k/[OpenAPI/Swagger] docs if you prefer. The link:https://github.com/OliveTin/OliveTin/blob/main/proto/olivetin/api/v1/olivetin.proto[Protobuf definition] is the source of truth for all request and response fields.

+ 1 - 1
frontend/package-lock.json

@@ -32,7 +32,7 @@
 				"vite": "^8.3.8"
 				"vite": "^8.3.8"
 			},
 			},
 			"engines": {
 			"engines": {
-				"node": "^22.13.0 || >=24"
+				"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
 			}
 			}
 		},
 		},
 		"node_modules/@babel/helper-string-parser": {
 		"node_modules/@babel/helper-string-parser": {

+ 1 - 1
frontend/package.json

@@ -37,6 +37,6 @@
 		"vue-router": "^5.5.0"
 		"vue-router": "^5.5.0"
 	},
 	},
 	"engines": {
 	"engines": {
-		"node": "^22.13.0 || >=24"
+		"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
 	}
 	}
 }
 }