@palettelab/cli 0.3.52 → 0.3.53

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/README.md CHANGED
@@ -783,6 +783,10 @@ If no plugin ID is provided, the CLI uses the current `palette-plugin.json` or `
783
783
  Inspect and generate OS-broker service integrations declared through
784
784
  `provides` and `consumes` in `palette-plugin.json`.
785
785
 
786
+ Use this command family when one Palette app needs governed data, approvals, or
787
+ events from another app. The CLI keeps the app manifest, local mocks, provider
788
+ schema files, and generated clients aligned with the broker contract.
789
+
786
790
  ```bash
787
791
  pltt init employee-management --template provider-app
788
792
  pltt init leave-management --template consumer-app
@@ -810,6 +814,38 @@ Generated TypeScript clients use the SDK's default `palette` client. Generated
810
814
  Python clients call `palette_sdk.services(ctx)`, so backend routes still pass
811
815
  through Palette's broker permission and install checks.
812
816
 
817
+ Recommended workflow:
818
+
819
+ 1. Provider app: implement backend methods with `@service(...)` and declare
820
+ event topics in `provides.events`.
821
+ 2. Provider app: run `pltt services sync` or `pltt services scaffold <method>`
822
+ to keep manifest methods and schema files current.
823
+ 3. Consumer app: run `pltt services add <target>` for each consumed service or
824
+ event, including a `--reason` for review and install UI.
825
+ 4. Consumer app: use `pltt services mock <target>` and `pltt services test
826
+ --offline` during local development.
827
+ 5. Consumer app: use `pltt services pull --env staging` to generate typed
828
+ clients from the live `/api/v1/os-broker/schemas` endpoint.
829
+ 6. Run `pltt test` before publish; contract checks include local
830
+ `provides`/`consumes`, mocks, schemas, and dependency-policy validation.
831
+
832
+ Runtime behavior:
833
+
834
+ - Service calls go through `POST /api/v1/os-broker/dispatch`.
835
+ - Event publishes go through `POST /api/v1/os-broker/events/emit`.
836
+ - Event subscriptions use `GET /api/v1/os-broker/events/stream`.
837
+ - Catalog and generated client metadata come from `/api/v1/os-broker/catalog`
838
+ and `/api/v1/os-broker/schemas`.
839
+ - Installs use `/api/v1/app-installs/<app_id>/dependency-plan` and can include
840
+ required provider apps with `?include_dependencies=true`.
841
+ - Org owners/admins can revoke or restore individual cross-app grants from
842
+ Settings > Apps; the broker checks those grants on every call and stream.
843
+
844
+ Provider methods can use inline JSON Schema objects or schema file paths in
845
+ `input_schema`, `input`, `output_schema`, and `output`. Event topics can use
846
+ `schema` or `payload_schema`. The CLI scaffolds schema files by default because
847
+ they are easier to review and reuse for generated clients.
848
+
813
849
  ## Global Flags
814
850
 
815
851
  - `--json` emits machine-readable output for `package`, `publish`, `status`, `logs`, `test`, and `version`.
@@ -693,7 +693,18 @@ token = await ctx.connections.access_token("google_calendar")
693
693
  ## 11. App-To-App Services
694
694
 
695
695
  Apps can expose governed broker services and events, then consume them from
696
- other installed apps without knowing another app's URL.
696
+ other installed apps without knowing another app's URL. The broker is the only
697
+ supported integration path for cross-app business data. Do not read another
698
+ app's database tables and do not call another app's private backend route
699
+ directly.
700
+
701
+ Palette enforces the app-to-app contract in four places:
702
+
703
+ - Manifest review: providers declare `provides`, consumers declare `consumes`.
704
+ - Install: required provider apps are resolved before the consumer is activated.
705
+ - Org grants: owners/admins can allow or revoke each consumed service/event.
706
+ - Runtime: every service call, event emit, and event stream is checked against
707
+ same-org install state, `consumes`, grants, and JSON Schemas.
697
708
 
698
709
  Provider apps declare a namespace and callable methods with `provides`:
699
710
 
@@ -705,25 +716,40 @@ Provider apps declare a namespace and callable methods with `provides`:
705
716
  {
706
717
  "id": "hr.directory",
707
718
  "methods": [
708
- { "name": "approvalChain.get", "input_schema": "schemas/approval-chain.input.json" }
719
+ {
720
+ "name": "approvalChain.get",
721
+ "input_schema": "schemas/approval-chain.input.json",
722
+ "output_schema": "schemas/approval-chain.output.json"
723
+ }
709
724
  ]
710
725
  }
711
726
  ],
712
- "events": [{ "topic": "hierarchy.updated" }]
727
+ "events": [
728
+ {
729
+ "topic": "hierarchy.updated",
730
+ "schema": "schemas/hierarchy-updated.json"
731
+ }
732
+ ]
713
733
  }
714
734
  }
715
735
  ```
716
736
 
717
- Expose the handler with `@service`:
737
+ Expose the handler with `@service`. The platform registers handlers when the
738
+ plugin loads and injects a full `PluginContext` at dispatch time:
718
739
 
719
740
  ```python
720
741
  from palette_sdk import PluginContext, service
721
742
 
722
- @service("approvalChain.get")
743
+ @service("approvalChain.get", scope="members:read")
723
744
  async def approval_chain(ctx: PluginContext, payload: dict) -> dict:
724
745
  return {"approvers": [{"user_id": ctx.user_id, "step": 1}]}
725
746
  ```
726
747
 
748
+ If a method also declares `route_method` and `route_path`, Palette can fall back
749
+ to signed internal HTTP transport when no in-process handler is registered. New
750
+ provider apps should prefer `@service(...)` because it avoids URL coupling and
751
+ keeps dispatch inside the broker lifecycle.
752
+
727
753
  Consumers declare qualified targets with `consumes`:
728
754
 
729
755
  ```json
@@ -746,8 +772,11 @@ Consumers declare qualified targets with `consumes`:
746
772
  The CLI can update the manifest and generate typed clients for those targets:
747
773
 
748
774
  ```bash
775
+ pltt services sync
749
776
  pltt services add hr/v1#approvalChain.get --reason "Route leave approvals through HR"
750
777
  pltt services add hr/v1#hierarchy.updated --event --optional
778
+ pltt services mock hr/v1#approvalChain.get
779
+ pltt services test --offline
751
780
  pltt services pull --env staging
752
781
  ```
753
782
 
@@ -764,12 +793,42 @@ from palette_sdk import services
764
793
 
765
794
  chain = await services(ctx).call("hr/v1#approvalChain.get", {"user_id": ctx.user_id})
766
795
  await ctx.events.emit("leave/v1#leave.requested", {"approval_chain": chain})
796
+ await ctx.events.emit_durable("leave/v1#leave.requested", {"approval_chain": chain})
767
797
  ```
768
798
 
769
799
  At install time, Palette checks required `consumes` targets and can show the
770
800
  provider apps that must also be installed. The org-level grant is saved on the
771
801
  install and the broker checks it on every call, emit, or event stream.
772
802
 
803
+ Useful platform endpoints when building or debugging integrations:
804
+
805
+ ```text
806
+ GET /api/v1/app-installs/{app_id}/dependency-plan
807
+ POST /api/v1/app-installs/{app_id}?include_dependencies=true
808
+ GET /api/v1/app-installs/{app_id}/cross-app-grants
809
+ PATCH /api/v1/app-installs/{app_id}/cross-app-grants
810
+ GET /api/v1/os-broker/catalog
811
+ GET /api/v1/os-broker/schemas?targets=hr/v1#approvalChain.get
812
+ GET /api/v1/os-broker/audit?app_id=leave-management
813
+ ```
814
+
815
+ Local simulator workflows can use `.palette/app-services.local.json` mocks.
816
+ The mock command writes the file for you:
817
+
818
+ ```bash
819
+ pltt services mock hr/v1#approvalChain.get
820
+ ```
821
+
822
+ Example mock:
823
+
824
+ ```json
825
+ {
826
+ "hr/v1#approvalChain.get": {
827
+ "approvers": [{ "user_id": "manager-1", "step": 1 }]
828
+ }
829
+ }
830
+ ```
831
+
773
832
  App storage is separate from Data Rooms. Use `ctx.storage` and `palette.storage` for app-owned files that go directly to the OS-configured storage backend, currently GCS in hosted environments. Use `ctx.data_rooms` or `palette.dataRooms` only when the file should be visible and governed as a Data Room document.
774
833
 
775
834
  Palette scopes storage the same way. Files written through `ctx.storage` or the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palettelab/cli",
3
- "version": "0.3.52",
3
+ "version": "0.3.53",
4
4
  "description": "Developer CLI for building Palette platform plugins — no platform source access required.",
5
5
  "bin": {
6
6
  "pltt": "bin/pltt.js"
@@ -4,7 +4,7 @@
4
4
  "private": true,
5
5
  "description": "A Palette platform plugin",
6
6
  "dependencies": {
7
- "@palettelab/sdk": "^0.1.22"
7
+ "@palettelab/sdk": "^0.1.23"
8
8
  },
9
9
  "devDependencies": {
10
10
  "typescript": "^5.0.0",
@@ -2,7 +2,7 @@
2
2
  "private": true,
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@palettelab/sdk": "^0.1.22",
5
+ "@palettelab/sdk": "^0.1.23",
6
6
  "react": "^19.0.0",
7
7
  "react-dom": "^19.0.0"
8
8
  }
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
5
  "dependencies": {
6
- "@palettelab/sdk": "^0.1.22",
6
+ "@palettelab/sdk": "^0.1.23",
7
7
  "react": "^19.0.0"
8
8
  }
9
9
  }
@@ -2,5 +2,5 @@
2
2
  "name": "my-db-plugin",
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
- "dependencies": { "@palettelab/sdk": "^0.1.22", "react": "^19.0.0" }
5
+ "dependencies": { "@palettelab/sdk": "^0.1.23", "react": "^19.0.0" }
6
6
  }
@@ -2,5 +2,5 @@
2
2
  "name": "my-external-svc",
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
- "dependencies": { "@palettelab/sdk": "^0.1.22", "react": "^19.0.0" }
5
+ "dependencies": { "@palettelab/sdk": "^0.1.23", "react": "^19.0.0" }
6
6
  }
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
5
  "dependencies": {
6
- "@palettelab/sdk": "^0.1.22",
6
+ "@palettelab/sdk": "^0.1.23",
7
7
  "react": "^19.0.0"
8
8
  }
9
9
  }
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
5
  "dependencies": {
6
- "@palettelab/sdk": "^0.1.22",
6
+ "@palettelab/sdk": "^0.1.23",
7
7
  "react": "^19.0.0"
8
8
  },
9
9
  "devDependencies": {
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
5
  "dependencies": {
6
- "@palettelab/sdk": "^0.1.22",
6
+ "@palettelab/sdk": "^0.1.23",
7
7
  "react": "^19.0.0"
8
8
  },
9
9
  "devDependencies": {
@@ -2,7 +2,7 @@
2
2
  "private": true,
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@palettelab/sdk": "^0.1.22",
5
+ "@palettelab/sdk": "^0.1.23",
6
6
  "react": "^19.0.0"
7
7
  }
8
8
  }