diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 823ea2e..f434de0 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -20,8 +20,12 @@ jobs: test -s README.md test -s docs/README.md test -s docs/v1/README.md + test -s docs/v1/quickstart.md grep -Fq '1.0.0-draft' docs/v1/README.md grep -Fq 'corelink_device_id' docs/v1/README.md + grep -Fq 'Authorization: Bearer $CORELINK_ACCESS_TOKEN' docs/v1/quickstart.md + grep -Fq 'Idempotency-Key: $CORELINK_IDEMPOTENCY_KEY' docs/v1/quickstart.md + grep -Fq '/api/v1/tenants/$CORELINK_TENANT_ID/devices' docs/v1/quickstart.md if grep -Fq 'API contract repository also has unpopulated' README.md; then echo "stale API-contract status returned" >&2 exit 1 diff --git a/README.md b/README.md index 657237a..cfe441f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ define the public API/event boundary. - [Documentation index](docs/README.md) - [v1 documentation](docs/v1/README.md) — targets the current `1.0.0-draft` public Device and Command contract and canonical event envelope. +- [30-minute v1 quickstart](docs/v1/quickstart.md) — bearer auth, tenant scope, + Device creation/read and idempotent Command submission using the public contract. CoreLink v1 is not a Stable release. TypeScript and Python clients are prerelease; Java SDK, CLI, MCP server and mock server remain Scaffold/Planned. diff --git a/docs/README.md b/docs/README.md index 4752c0b..31e4903 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,7 @@ | Docs version | Contract target | Status | Entry point | | --- | --- | --- | --- | -| v1 | `corelink-public-v1.yaml` `1.0.0-draft` | Alpha documentation for a draft public boundary | [v1](v1/README.md) | +| v1 | `corelink-public-v1.yaml` `1.0.0-draft` | Alpha docs + contract-backed quickstart | [v1](v1/README.md) · [30-minute quickstart](v1/quickstart.md) | ## Versioning policy diff --git a/docs/v1/README.md b/docs/v1/README.md index 7da70f9..a454644 100644 --- a/docs/v1/README.md +++ b/docs/v1/README.md @@ -14,7 +14,7 @@ boundary until separately reviewed. | --- | --- | --- | | Public Device + Command API | Alpha / draft | [Public OpenAPI](https://github.com/CoreLinkPlatform/api-contracts/blob/main/openapi/corelink-public-v1.yaml) | | Event envelope | Alpha / draft | [AsyncAPI](https://github.com/CoreLinkPlatform/api-contracts/blob/main/asyncapi/corelink-events-v1.yaml) | -| Authentication and tenant scope | Planned documentation | Contract security definitions + runtime evidence | +| Authentication and tenant scope | Alpha quickstart | [30-minute quickstart](quickstart.md) + contract security definitions | | TypeScript SDK | Prerelease Alpha | [sdk-typescript](https://github.com/CoreLinkPlatform/sdk-typescript) | | Python SDK | Prerelease Alpha | [sdk-python](https://github.com/CoreLinkPlatform/sdk-python) | | Java SDK | Scaffold / Planned | [sdk-java](https://github.com/CoreLinkPlatform/sdk-java) | @@ -25,8 +25,10 @@ boundary until separately reviewed. ## Navigation contract ### 1. Start here -Concepts, authentication, tenant isolation, canonical identifiers and first -verified API call. Content beyond the linked contract is **Planned**. +Begin with the [30-minute v1 quickstart](quickstart.md) for bearer authentication, +tenant scoping, Device and Command calls, idempotency, failure handling and a +repeatable acceptance record. Content beyond the linked Device/Command contract +is **Planned**. ### 2. Guides Device registration/lifecycle and commands are first because they are in the diff --git a/docs/v1/quickstart.md b/docs/v1/quickstart.md new file mode 100644 index 0000000..175e1a3 --- /dev/null +++ b/docs/v1/quickstart.md @@ -0,0 +1,185 @@ +# 30-minute CoreLink v1 quickstart + +**Maturity: Alpha documentation / `1.0.0-draft` public contract** + +This quickstart exercises the currently reviewed public Device and Command slice +without depending on a prerelease SDK. It uses the versioned OpenAPI contract as +the source of truth: + +- [CoreLink public v1 OpenAPI](https://github.com/CoreLinkPlatform/api-contracts/blob/main/openapi/corelink-public-v1.yaml) +- public authentication: bearer JWT; +- public tenant scope: `tenant_id` in the resource path; +- public device identity: `corelink_device_id`. + +The contract is still draft. The examples below demonstrate the accepted +contract shape; they do not claim that a public production endpoint, self-service +token issuer, or Stable SDK release exists. + +## Target outcome + +Within 30 minutes you should be able to: + +1. configure an assigned API base URL, bearer token and tenant; +2. verify readiness; +3. list the tenant's devices; +4. create a device when a valid `device_model_id` has been assigned; +5. create an idempotent command for that device; +6. inspect the command and recognize the standard failure responses. + +## 0–5 min: prerequisites + +You need values supplied by the CoreLink environment/operator: + +- `CORELINK_API_URL` — base URL for the environment you are authorized to use; +- `CORELINK_ACCESS_TOKEN` — bearer JWT for that environment; +- `CORELINK_TENANT_ID` — UUID of the tenant you are authorized to access; +- `CORELINK_DEVICE_MODEL_ID` — UUID of an allowed device model if you will + create a device. + +The draft public contract does **not** define a token-issuance endpoint. Do not +invent or hard-code a client-secret flow in application code. Obtain credentials +through the environment's approved onboarding path. + +Set the values in your shell without committing them: + +```bash +export CORELINK_API_URL="https://api.example.invalid" +export CORELINK_ACCESS_TOKEN="" +export CORELINK_TENANT_ID="" +export CORELINK_DEVICE_MODEL_ID="" +``` + +Use a real environment URL in place of `api.example.invalid`. Keep tokens out of +shell history, screenshots, issue bodies and source control where practical. + +## 5–10 min: verify the environment + +The readiness endpoint is intentionally unauthenticated: + +```bash +curl --fail-with-body --silent --show-error \ + "$CORELINK_API_URL/health/ready" +``` + +A ready environment returns HTTP `200`. HTTP `503` means a dependency required +for traffic is unavailable; stop and resolve the environment before continuing. + +## 10–15 min: list tenant-scoped devices + +```bash +curl --fail-with-body --silent --show-error \ + -H "Authorization: Bearer $CORELINK_ACCESS_TOKEN" \ + "$CORELINK_API_URL/api/v1/tenants/$CORELINK_TENANT_ID/devices?limit=20&offset=0" +``` + +The response is a `DevicePage`. Device identifiers exposed by the public API are +`corelink_device_id`; connector/provider identifiers are not public resource +identities. + +Expected authorization failures: + +- `401` — authentication is missing or invalid; +- `403` — the caller is authenticated but cannot access the requested tenant + or operation. + +Never recover from `403` by changing the tenant ID to another tenant. + +## 15–20 min: create a device + +Skip this step if the environment has not assigned a valid +`CORELINK_DEVICE_MODEL_ID`. + +```bash +DEVICE_RESPONSE="$(curl --fail-with-body --silent --show-error \ + -X POST \ + -H "Authorization: Bearer $CORELINK_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + "$CORELINK_API_URL/api/v1/tenants/$CORELINK_TENANT_ID/devices" \ + --data "{\"device_model_id\":\"$CORELINK_DEVICE_MODEL_ID\",\"name\":\"quickstart-device\",\"metadata\":{\"source\":\"docs-v1-quickstart\"}}")" + +printf '%s\n' "$DEVICE_RESPONSE" +``` + +A successful create returns HTTP `201` and a `Device` containing +`corelink_device_id`. Record that value as `CORELINK_DEVICE_ID`: + +```bash +export CORELINK_DEVICE_ID="" +``` + +HTTP `400` means the request is invalid; `401`/`403` are authentication or +tenant/permission failures; `409` means the request conflicts with current +state. + +## 20–25 min: submit one idempotent command + +The command create operation requires `Idempotency-Key`. Reuse the same key +only when retrying the same logical command. + +```bash +export CORELINK_IDEMPOTENCY_KEY="quickstart-$(date +%s)" + +COMMAND_RESPONSE="$(curl --fail-with-body --silent --show-error \ + -X POST \ + -H "Authorization: Bearer $CORELINK_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "Idempotency-Key: $CORELINK_IDEMPOTENCY_KEY" \ + "$CORELINK_API_URL/api/v1/tenants/$CORELINK_TENANT_ID/devices/$CORELINK_DEVICE_ID/commands" \ + --data '{"command_type":"quickstart.ping","payload":{},"metadata":{"source":"docs-v1-quickstart"}}')" + +printf '%s\n' "$COMMAND_RESPONSE" +``` + +A successful submission returns HTTP `201` and a `Command`. Record its +`command_id`: + +```bash +export CORELINK_COMMAND_ID="" +``` + +Command status is one of `queued`, `dispatching`, `sent`, `acknowledged`, +`succeeded`, `failed`, `timed_out`, or `cancelled`. A `201` response +means the command was accepted; it does not mean device execution succeeded. + +## 25–30 min: inspect the command + +```bash +curl --fail-with-body --silent --show-error \ + -H "Authorization: Bearer $CORELINK_ACCESS_TOKEN" \ + "$CORELINK_API_URL/api/v1/tenants/$CORELINK_TENANT_ID/devices/$CORELINK_DEVICE_ID/commands/$CORELINK_COMMAND_ID" +``` + +Expected failures use the contract's `application/problem+json` shape and carry +a `correlation_id` for diagnosis. Preserve that identifier when escalating an +unexpected error. + +## Tenant-isolation check + +If you have two explicitly authorized test tenants, repeat a read with the token +and tenant combination provided for each environment. A token must never gain +access merely because a caller changes `tenant_id` in the URL. Do not probe +tenants you are not authorized to test. + +## Safe retry rules + +- GET requests may be retried according to the environment's documented policy. +- For command POST retries, retain the original `Idempotency-Key`. +- Do not automatically retry `400`, `401`, `403`, or `404`. +- Treat `409` as a state/idempotency conflict that needs reconciliation. +- A readiness `503` is an environment/dependency failure, not proof that a + write failed or succeeded. + +## Definition of a successful quickstart + +The quickstart is complete when the developer has retained: + +- the environment/contract baseline used; +- the authorized tenant ID; +- one successful tenant-scoped read; +- one `corelink_device_id` from an existing or newly created device; +- one command ID plus its observed terminal or current state; +- any failure `correlation_id` needed for follow-up. + +For SDK usage, sandbox packaging and broader resource guides, follow their +repository maturity. TypeScript/Python are prerelease Alpha; Java, CLI, MCP and +mock-server remain Scaffold/Planned until their release gates pass.