@homespunapps/core 1.4.2 → 1.4.3

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/dist/client.d.ts CHANGED
@@ -553,6 +553,22 @@ export declare class HomespunClient {
553
553
  decision: "approve" | "reject";
554
554
  note?: string;
555
555
  }): Promise<CommunitySubmissionDetail>;
556
+ /**
557
+ * GET /v1/community/templates/:ref/config-contract: the install-time config
558
+ * contract for an installable template (its settings collection + the ordered
559
+ * keyed config/upload steps). Use it to discover what a template needs and to
560
+ * pre-upload files for `upload` steps (POST /v1/attachments) before install.
561
+ */
562
+ getCommunityConfigContract(ref: string): Promise<CommunityConfigContract>;
563
+ /**
564
+ * POST /v1/community/templates/:ref/install: install a community template for
565
+ * the calling agent's owning human. `config` is `{ [stepKey]: value }` where a
566
+ * `config` step's value is a string and an `upload` step's value is an
567
+ * attachment id the agent pre-uploaded (agent-scoped) via `uploadBlob()` /
568
+ * `uploadBlobInline()`; the relay re-points it to the new app on install.
569
+ * Installs always create; returns the new app's id, slug, and url.
570
+ */
571
+ installCommunityTemplate(ref: string, config?: Record<string, unknown>): Promise<CommunityInstallResult>;
556
572
  /** GET /v1/publisher: the caller's own publisher profile. */
557
573
  getPublisher(): Promise<PublisherProfile>;
558
574
  /** POST /v1/publisher/claim: set the handle once (permanent after claiming). */
@@ -1001,6 +1017,61 @@ export interface CommunitySetupStep {
1001
1017
  * (letters, digits, '_', up to 64 chars).
1002
1018
  */
1003
1019
  key?: string;
1020
+ /**
1021
+ * The manifest `ingest` rule this step wires up (D7). Allowed ONLY on a
1022
+ * `connect` step, optional there. Publish rejects a name the manifest does
1023
+ * not declare. After install, the installer pastes that rule's freshly
1024
+ * provisioned hook URL into the external service.
1025
+ */
1026
+ ingestRule?: string;
1027
+ }
1028
+ /**
1029
+ * One keyed config/upload step in a template's install-time config contract
1030
+ * (install-config programme, PR 4). Field names are the wire shape (snake_case
1031
+ * `value_hint`). An `upload` step's answer is an attachment id string.
1032
+ */
1033
+ export interface CommunityConfigStep {
1034
+ key: string;
1035
+ kind: "config" | "upload";
1036
+ label: string;
1037
+ description?: string;
1038
+ required: boolean;
1039
+ secret: boolean;
1040
+ choices?: string[];
1041
+ default?: string;
1042
+ value_hint?: string;
1043
+ }
1044
+ /**
1045
+ * One `connect` step in a template's contract that wires up an INBOUND hook:
1046
+ * after install, the app's own freshly provisioned hook URL for `ingest_rule`
1047
+ * has to be pasted into the external service the step describes. Read the URLs
1048
+ * from `GET /v1/apps/:app_id/ingest-hooks` once the install returns.
1049
+ */
1050
+ export interface CommunityConnectStep {
1051
+ label: string;
1052
+ description?: string;
1053
+ ingest_rule: string;
1054
+ /** Collection the hook writes into, or null when the rule went missing. */
1055
+ collection: string | null;
1056
+ mode: "append" | "upsert" | null;
1057
+ }
1058
+ /** The install-time config contract for an installable community template. */
1059
+ export interface CommunityConfigContract {
1060
+ snapshot_id: string;
1061
+ name: string;
1062
+ slug: string | null;
1063
+ /** The manifest's declared settings collection, or null when none. */
1064
+ settings_collection: string | null;
1065
+ /** Ordered keyed config/upload steps; empty when the template needs none. */
1066
+ config_steps: CommunityConfigStep[];
1067
+ /** Ordered connect steps that name an ingest rule; empty when none. */
1068
+ connect_steps: CommunityConnectStep[];
1069
+ }
1070
+ /** Result of an agent-key community install (installs always create). */
1071
+ export interface CommunityInstallResult {
1072
+ app_id: string;
1073
+ slug: string;
1074
+ url: string;
1004
1075
  }
1005
1076
  export interface PublishCommunityTemplateRequest {
1006
1077
  /** The owned app to publish. */
@@ -1149,6 +1220,26 @@ export interface CommunitySubmissionDetail extends CommunitySubmissionSummary {
1149
1220
  * the template declares no steps.
1150
1221
  */
1151
1222
  setup_steps: CommunitySetupStep[] | null;
1223
+ /**
1224
+ * Every external destination the manifest declares (D6 disclosure): outbound
1225
+ * webhook targets, the app's fetch allowance and its framing allowance,
1226
+ * deduplicated and HOSTS ONLY, so a reviewer sees where the app can send
1227
+ * data without reading the raw manifest. Empty when it talks to nothing
1228
+ * outside Homespun.
1229
+ */
1230
+ external_destinations: CommunityExternalDestination[];
1231
+ }
1232
+ /** One disclosed external destination on a submission (D6). */
1233
+ export interface CommunityExternalDestination {
1234
+ /** `webhook` = the relay POSTs row data there; `fetch` / `embed` = the app's
1235
+ * own page may call or frame it. */
1236
+ kind: "webhook" | "embed" | "fetch";
1237
+ /** Destination host, or null when the manifest alone cannot name it. */
1238
+ host: string | null;
1239
+ /** Settings field an install-time webhook target is read from. */
1240
+ fromSetting?: string;
1241
+ /** Stored connection a relative webhook target resolves against. */
1242
+ viaConnection?: string;
1152
1243
  }
1153
1244
  /** A publisher's own profile, as returned by the `/v1/publisher` routes. */
1154
1245
  export interface PublisherProfile {
package/dist/client.js CHANGED
@@ -675,9 +675,13 @@ export class HomespunClient {
675
675
  // (humanId/createdAt), matching packages/relay/src/http/routes/app-members.ts
676
676
  // exactly rather than the usual snake_case convention.
677
677
  //
678
- // Template `install`/`uninstall` is intentionally NOT wrapped here — that
679
- // route is `requireHuman` (human login cookie only), not agent-key
680
- // authorizable, so it has no place on this agent-facing client.
678
+ // Community template install IS agent-key authorizable and wrapped below
679
+ // (getCommunityConfigContract + installCommunityTemplate): the calling agent
680
+ // installs a community template for its OWNING human, who becomes the app's
681
+ // installer/owner, reusing the SAME core install path as the human web form.
682
+ // Trials, keep, and the first-party app `uninstall` stay human-only web flows
683
+ // (a countdown banner and a confirm page have no agent-key equivalent), so
684
+ // those remain intentionally unwrapped here.
681
685
  // -------------------------------------------------------------------------
682
686
  /**
683
687
  * POST /v1/apps/:id/members — add or invite a member by email. If a Human
@@ -1012,6 +1016,38 @@ export class HomespunClient {
1012
1016
  return this.asObject(r);
1013
1017
  }
1014
1018
  // -------------------------------------------------------------------------
1019
+ // Agent-key community install (install-config programme, PR 4). Both act AS
1020
+ // the calling agent's owning human, who becomes the installed app's owner. A
1021
+ // `ref` is a namespaced `<handle>/<slug>` OR a community snapshot id;
1022
+ // encodeURIComponent keeps a namespaced ref one path segment on the wire.
1023
+ // -------------------------------------------------------------------------
1024
+ /**
1025
+ * GET /v1/community/templates/:ref/config-contract: the install-time config
1026
+ * contract for an installable template (its settings collection + the ordered
1027
+ * keyed config/upload steps). Use it to discover what a template needs and to
1028
+ * pre-upload files for `upload` steps (POST /v1/attachments) before install.
1029
+ */
1030
+ async getCommunityConfigContract(ref) {
1031
+ const r = await this.call("GET", `/v1/community/templates/${encodeURIComponent(ref)}/config-contract`);
1032
+ if (!r.ok)
1033
+ this.fail(r);
1034
+ return this.asObject(r);
1035
+ }
1036
+ /**
1037
+ * POST /v1/community/templates/:ref/install: install a community template for
1038
+ * the calling agent's owning human. `config` is `{ [stepKey]: value }` where a
1039
+ * `config` step's value is a string and an `upload` step's value is an
1040
+ * attachment id the agent pre-uploaded (agent-scoped) via `uploadBlob()` /
1041
+ * `uploadBlobInline()`; the relay re-points it to the new app on install.
1042
+ * Installs always create; returns the new app's id, slug, and url.
1043
+ */
1044
+ async installCommunityTemplate(ref, config) {
1045
+ const r = await this.call("POST", `/v1/community/templates/${encodeURIComponent(ref)}/install`, config !== undefined ? { config } : {});
1046
+ if (!r.ok)
1047
+ this.fail(r);
1048
+ return this.asObject(r);
1049
+ }
1050
+ // -------------------------------------------------------------------------
1015
1051
  // Community publisher identity (marketplace PR 1). All three act AS the
1016
1052
  // calling agent's owning human. claim/update additionally need a verified
1017
1053
  // email server-side.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homespunapps/core",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Homespun relay client: typed HTTP + WebSocket operations against a Homespun relay. Framework-free.",
5
5
  "license": "MIT",
6
6
  "type": "module",