@camstack/types 1.2.53 → 1.2.54

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.
@@ -6,6 +6,65 @@ import { type InferProvider } from './capability-definition.js';
6
6
  * Each provider returns a static descriptor; the core enumerates them
7
7
  * to validate the `integration=` query param and resolve the consent
8
8
  * label + the scopes baked into the issued token.
9
+ *
10
+ * ## Declaring one
11
+ *
12
+ * An OAuth client is integration-specific knowledge — who the client is, what
13
+ * it may ask for, where it may be sent — so it is declared by the ADDON that
14
+ * owns the integration, never by the kernel and never as a branch inside
15
+ * `oauth2-routes.ts` ([D101](../../../../docs/decisions/adr-0101.md)). Three
16
+ * steps, no others:
17
+ *
18
+ * 1. Add `{ "name": "oauth-integration" }` to the addon's `camstack.addons[]`
19
+ * manifest entry. This is also what tells the hub, at addon-LOAD time, that
20
+ * a descriptor is owed — see "the boot window" below.
21
+ * 2. Return a provider from `onInitialize()`:
22
+ *
23
+ * ```ts
24
+ * const provider: IOauthIntegrationProvider = {
25
+ * getDescriptor: async () => ({
26
+ * integrationId: 'my-thing', // the `integration=` query param
27
+ * displayName: 'My Thing',
28
+ * requestedScopes: [ … ], // see below
29
+ * allowedRedirectPrefixes: ['https://callback.example/'],
30
+ * }),
31
+ * }
32
+ * return [{ capability: oauthIntegrationCapability, provider }]
33
+ * ```
34
+ *
35
+ * The descriptor must be **static** — it is read on the authorize path, so
36
+ * never put an await on network or disk behind it, and never register it
37
+ * behind one either (a provider is registered only once `onInitialize`
38
+ * RETURNS, so anything awaited before the return delays linking).
39
+ * 3. Nothing else. There is no allow-list to join, no id to register with the
40
+ * core, and no per-integration branch anywhere: `/api/oauth2/authorize` and
41
+ * `/api/oauth2/integrations` are built from this collection alone.
42
+ *
43
+ * **Scopes.** `requestedScopes` is baked into every token this integration is
44
+ * ever issued and the operator consents to it once. Derive it from the tRPC
45
+ * paths the client calls **with that token**, against `METHOD_ACCESS_MAP`, and
46
+ * prefer a narrow `capability:` scope to a `category:` one unless the client
47
+ * genuinely needs a whole family. A category scope grants every future member
48
+ * of that category too. `category:system [create]` has been rejected once and
49
+ * should stay rejected: it hands `addons.installPackage` to an integration.
50
+ *
51
+ * What it does NOT cover: calls the ADDON makes over `ctx.api`, which run as
52
+ * the addon and are not scope-checked. Alexa's descriptor is narrower than
53
+ * Home Assistant's for exactly that reason — its Lambda posts directives and
54
+ * the addon does the work, while the Home Assistant component calls tRPC
55
+ * directly with the token. So `requestedScopes` describes the blast radius of
56
+ * the GRANT, not the reach of the integration; do not widen one to describe the
57
+ * other.
58
+ *
59
+ * **The boot window.** An addon registers its provider after its runner forks
60
+ * and initialises, so between hub start and that moment this collection is
61
+ * incomplete and an `integrationId` can be legitimately absent. The core does
62
+ * not wait, poll or cache around this ([D3](../../../../docs/decisions/adr-0003.md)):
63
+ * it compares the manifest declarers against the registered providers and
64
+ * answers `503 temporarily_unavailable` (with `Retry-After` and the pending
65
+ * addon ids) instead of `400 unknown integration`, and reports
66
+ * `complete: false` on `GET /api/oauth2/integrations`. A client should retry
67
+ * while the list is incomplete rather than conclude the hub cannot do OAuth.
9
68
  */
10
69
  declare const OauthIntegrationDescriptorSchema: z.ZodObject<{
11
70
  integrationId: z.ZodString;
package/dist/index.js CHANGED
@@ -13012,6 +13012,65 @@ var ScopedTokenSchema = zod.z.object({
13012
13012
  * Each provider returns a static descriptor; the core enumerates them
13013
13013
  * to validate the `integration=` query param and resolve the consent
13014
13014
  * label + the scopes baked into the issued token.
13015
+ *
13016
+ * ## Declaring one
13017
+ *
13018
+ * An OAuth client is integration-specific knowledge — who the client is, what
13019
+ * it may ask for, where it may be sent — so it is declared by the ADDON that
13020
+ * owns the integration, never by the kernel and never as a branch inside
13021
+ * `oauth2-routes.ts` ([D101](../../../../docs/decisions/adr-0101.md)). Three
13022
+ * steps, no others:
13023
+ *
13024
+ * 1. Add `{ "name": "oauth-integration" }` to the addon's `camstack.addons[]`
13025
+ * manifest entry. This is also what tells the hub, at addon-LOAD time, that
13026
+ * a descriptor is owed — see "the boot window" below.
13027
+ * 2. Return a provider from `onInitialize()`:
13028
+ *
13029
+ * ```ts
13030
+ * const provider: IOauthIntegrationProvider = {
13031
+ * getDescriptor: async () => ({
13032
+ * integrationId: 'my-thing', // the `integration=` query param
13033
+ * displayName: 'My Thing',
13034
+ * requestedScopes: [ … ], // see below
13035
+ * allowedRedirectPrefixes: ['https://callback.example/'],
13036
+ * }),
13037
+ * }
13038
+ * return [{ capability: oauthIntegrationCapability, provider }]
13039
+ * ```
13040
+ *
13041
+ * The descriptor must be **static** — it is read on the authorize path, so
13042
+ * never put an await on network or disk behind it, and never register it
13043
+ * behind one either (a provider is registered only once `onInitialize`
13044
+ * RETURNS, so anything awaited before the return delays linking).
13045
+ * 3. Nothing else. There is no allow-list to join, no id to register with the
13046
+ * core, and no per-integration branch anywhere: `/api/oauth2/authorize` and
13047
+ * `/api/oauth2/integrations` are built from this collection alone.
13048
+ *
13049
+ * **Scopes.** `requestedScopes` is baked into every token this integration is
13050
+ * ever issued and the operator consents to it once. Derive it from the tRPC
13051
+ * paths the client calls **with that token**, against `METHOD_ACCESS_MAP`, and
13052
+ * prefer a narrow `capability:` scope to a `category:` one unless the client
13053
+ * genuinely needs a whole family. A category scope grants every future member
13054
+ * of that category too. `category:system [create]` has been rejected once and
13055
+ * should stay rejected: it hands `addons.installPackage` to an integration.
13056
+ *
13057
+ * What it does NOT cover: calls the ADDON makes over `ctx.api`, which run as
13058
+ * the addon and are not scope-checked. Alexa's descriptor is narrower than
13059
+ * Home Assistant's for exactly that reason — its Lambda posts directives and
13060
+ * the addon does the work, while the Home Assistant component calls tRPC
13061
+ * directly with the token. So `requestedScopes` describes the blast radius of
13062
+ * the GRANT, not the reach of the integration; do not widen one to describe the
13063
+ * other.
13064
+ *
13065
+ * **The boot window.** An addon registers its provider after its runner forks
13066
+ * and initialises, so between hub start and that moment this collection is
13067
+ * incomplete and an `integrationId` can be legitimately absent. The core does
13068
+ * not wait, poll or cache around this ([D3](../../../../docs/decisions/adr-0003.md)):
13069
+ * it compares the manifest declarers against the registered providers and
13070
+ * answers `503 temporarily_unavailable` (with `Retry-After` and the pending
13071
+ * addon ids) instead of `400 unknown integration`, and reports
13072
+ * `complete: false` on `GET /api/oauth2/integrations`. A client should retry
13073
+ * while the list is incomplete rather than conclude the hub cannot do OAuth.
13015
13074
  */
13016
13075
  var OauthIntegrationDescriptorSchema = zod.z.object({
13017
13076
  /** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
package/dist/index.mjs CHANGED
@@ -13011,6 +13011,65 @@ var ScopedTokenSchema = z.object({
13011
13011
  * Each provider returns a static descriptor; the core enumerates them
13012
13012
  * to validate the `integration=` query param and resolve the consent
13013
13013
  * label + the scopes baked into the issued token.
13014
+ *
13015
+ * ## Declaring one
13016
+ *
13017
+ * An OAuth client is integration-specific knowledge — who the client is, what
13018
+ * it may ask for, where it may be sent — so it is declared by the ADDON that
13019
+ * owns the integration, never by the kernel and never as a branch inside
13020
+ * `oauth2-routes.ts` ([D101](../../../../docs/decisions/adr-0101.md)). Three
13021
+ * steps, no others:
13022
+ *
13023
+ * 1. Add `{ "name": "oauth-integration" }` to the addon's `camstack.addons[]`
13024
+ * manifest entry. This is also what tells the hub, at addon-LOAD time, that
13025
+ * a descriptor is owed — see "the boot window" below.
13026
+ * 2. Return a provider from `onInitialize()`:
13027
+ *
13028
+ * ```ts
13029
+ * const provider: IOauthIntegrationProvider = {
13030
+ * getDescriptor: async () => ({
13031
+ * integrationId: 'my-thing', // the `integration=` query param
13032
+ * displayName: 'My Thing',
13033
+ * requestedScopes: [ … ], // see below
13034
+ * allowedRedirectPrefixes: ['https://callback.example/'],
13035
+ * }),
13036
+ * }
13037
+ * return [{ capability: oauthIntegrationCapability, provider }]
13038
+ * ```
13039
+ *
13040
+ * The descriptor must be **static** — it is read on the authorize path, so
13041
+ * never put an await on network or disk behind it, and never register it
13042
+ * behind one either (a provider is registered only once `onInitialize`
13043
+ * RETURNS, so anything awaited before the return delays linking).
13044
+ * 3. Nothing else. There is no allow-list to join, no id to register with the
13045
+ * core, and no per-integration branch anywhere: `/api/oauth2/authorize` and
13046
+ * `/api/oauth2/integrations` are built from this collection alone.
13047
+ *
13048
+ * **Scopes.** `requestedScopes` is baked into every token this integration is
13049
+ * ever issued and the operator consents to it once. Derive it from the tRPC
13050
+ * paths the client calls **with that token**, against `METHOD_ACCESS_MAP`, and
13051
+ * prefer a narrow `capability:` scope to a `category:` one unless the client
13052
+ * genuinely needs a whole family. A category scope grants every future member
13053
+ * of that category too. `category:system [create]` has been rejected once and
13054
+ * should stay rejected: it hands `addons.installPackage` to an integration.
13055
+ *
13056
+ * What it does NOT cover: calls the ADDON makes over `ctx.api`, which run as
13057
+ * the addon and are not scope-checked. Alexa's descriptor is narrower than
13058
+ * Home Assistant's for exactly that reason — its Lambda posts directives and
13059
+ * the addon does the work, while the Home Assistant component calls tRPC
13060
+ * directly with the token. So `requestedScopes` describes the blast radius of
13061
+ * the GRANT, not the reach of the integration; do not widen one to describe the
13062
+ * other.
13063
+ *
13064
+ * **The boot window.** An addon registers its provider after its runner forks
13065
+ * and initialises, so between hub start and that moment this collection is
13066
+ * incomplete and an `integrationId` can be legitimately absent. The core does
13067
+ * not wait, poll or cache around this ([D3](../../../../docs/decisions/adr-0003.md)):
13068
+ * it compares the manifest declarers against the registered providers and
13069
+ * answers `503 temporarily_unavailable` (with `Retry-After` and the pending
13070
+ * addon ids) instead of `400 unknown integration`, and reports
13071
+ * `complete: false` on `GET /api/oauth2/integrations`. A client should retry
13072
+ * while the list is incomplete rather than conclude the hub cannot do OAuth.
13014
13073
  */
13015
13074
  var OauthIntegrationDescriptorSchema = z.object({
13016
13075
  /** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.53",
3
+ "version": "1.2.54",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",