@palettelab/cli 0.3.35 → 0.3.36

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
@@ -275,7 +275,8 @@ async def create_invoice(body: InvoiceIn, ctx: PluginContext = Depends(get_plugi
275
275
 
276
276
  Backend SDK features for app-owned data:
277
277
 
278
- - `PluginContext` exposes `user_id`, `organization_id`, `plugin_id`, `permissions`, `config`, `storage`, `ctx.db`, `ctx.members`, `ctx.redis`, and `ctx.vector`.
278
+ - `PluginRouter`, `PluginContext`, and `get_plugin_context` provide the FastAPI route and request-context surface.
279
+ - `PluginContext` exposes `user_id`, `organization_id`, `org_role`, `plugin_id`, `permissions`, `storage`, `ctx.db`, `ctx.data_rooms`, `ctx.members`, `ctx.redis`, `ctx.vector`, `ctx.config`, and `ctx.logger`.
279
280
  - `ctx.db` is the full scoped SQLAlchemy `AsyncSession` for app-owned database data.
280
281
  - `ctx.repo(Model)` gives org-safe CRUD helpers for app tables.
281
282
  - `ctx.data_rooms` gives backend access to Palette Data Rooms without importing platform internals.
@@ -283,10 +284,19 @@ Backend SDK features for app-owned data:
283
284
  - `ctx.has_permission("...")`, `ctx.has_any_permission([...])`, and `ctx.has_all_permissions([...])` check declared permissions.
284
285
  - `ctx.config_value("key")` and `ctx.require_config("key")` read app install/config values.
285
286
  - `ctx.secret("KEY")` reads app secrets from config or environment variables.
287
+ - `get_config(ctx, key)` and `require_config(ctx, key)` are functional config helper forms.
288
+ - `require_permission(permission)`, `KNOWN_PERMISSIONS`, and `is_known_permission(permission)` support route and manifest permission checks.
286
289
  - `ctx.redis` gives a Redis-backed, plugin/org-scoped Redis API when `"redis"` is declared in `platform_services`.
287
290
  - `ctx.vector` gives a Qdrant-backed, plugin/org-scoped vector API when `"vector"` is declared in `platform_services`.
288
291
  - `LifecycleHooks` lets apps define install/update/enable/disable/uninstall hooks.
289
292
  - `OrgScopedTable` and `PluginBase` keep app data inside the plugin schema model set.
293
+ - `plugin_safe_id(...)`, `plugin_schema(...)`, `plugin_table_prefix(...)`, and `ensure_org_rls(...)` keep database names and row-level security consistent.
294
+ - `Event` and `subscribe_event(...)` register in-process platform event handlers.
295
+ - `sign_webhook(...)` and `verify_webhook_signature(...)` handle HMAC-SHA256 webhook signing checks.
296
+ - `ToolDefinition` is the base class for custom agent tools.
297
+ - `PluginManifest` and `load_manifest(...)` parse and validate `palette-plugin.json`.
298
+ - `SuccessResponse`, `ErrorResponse`, and `PaginatedResponse` are reusable response schemas.
299
+ - `route_permission_issues(router, public_routes=None)` is the test helper for detecting ungated backend routes.
290
300
 
291
301
  Python backend Data Room example:
292
302
 
@@ -524,7 +534,7 @@ await ctx.redis.incr("counter")
524
534
  await ctx.redis.decr("counter")
525
535
  await ctx.redis.scan(prefix="cache:", limit=100)
526
536
 
527
- # Redis hashes, lists, sets, sorted sets, streams, locks
537
+ # Redis hashes, lists, sets, sorted sets, queues, locks
528
538
  await ctx.redis.hset("hash", "field", {"value": 1})
529
539
  await ctx.redis.hgetall("hash")
530
540
  await ctx.redis.lpush("queue", {"job": 1})
@@ -533,8 +543,8 @@ await ctx.redis.sadd("tags", "red", "blue")
533
543
  await ctx.redis.smembers("tags")
534
544
  await ctx.redis.zadd("scores", {"alice": 10})
535
545
  await ctx.redis.zrange("scores", 0, -1, with_scores=True)
536
- await ctx.redis.xadd("events", {"type": "created"})
537
- await ctx.redis.xread({"events": "0-0"}, count=10)
546
+ await ctx.redis.enqueue("jobs", {"task": "sync"})
547
+ await ctx.redis.dequeue("jobs")
538
548
  await ctx.redis.lock("invoice:1", token, ttl=30)
539
549
  await ctx.redis.unlock("invoice:1", token)
540
550
 
@@ -125,6 +125,34 @@ Available context values:
125
125
  | `ctx.require_config(key)` | Read required config or raise |
126
126
  | `ctx.secret(key, default)` | Read a secret from app config or environment |
127
127
 
128
+ ## 4a. Backend Helper API Index
129
+
130
+ These are the public Python helpers exported by `palette_sdk`.
131
+
132
+ | Helper | Use it for |
133
+ |---|---|
134
+ | `PluginRouter` | FastAPI router mounted under `/api/v1/plugins/<plugin-id>` |
135
+ | `PluginContext`, `get_plugin_context` | Authenticated request context dependency |
136
+ | `MissingSecretError` | Handling missing required declared secrets from `ctx.secret(...)` |
137
+ | `require_permission(permission)` | Route-level permission gate required for protected routes |
138
+ | `KNOWN_PERMISSIONS`, `is_known_permission(...)` | Permission vocabulary checks for manifests/tools |
139
+ | `DataRoomsClient`, `ctx.data_rooms` | Backend Data Room room/folder/file helpers |
140
+ | `OrganizationMembersClient`, `ctx.members` | Current-organization member lookup, invite, and role helpers |
141
+ | `OrgRepository`, `ctx.repo(Model)` | Org-safe convenience CRUD for app-owned models |
142
+ | `PluginBase`, `OrgScopedTable` | SQLAlchemy declarative bases for plugin-owned tables |
143
+ | `ensure_org_rls(op, table)` | Alembic helper that enables org row-level security |
144
+ | `plugin_safe_id(...)`, `plugin_schema(...)`, `plugin_table_prefix(...)` | Manifest id to database-safe naming helpers |
145
+ | `get_config(ctx, key)`, `require_config(ctx, key)` | Functional form of config reads when not using `ctx.config_value(...)` |
146
+ | `LocalRedisService`, `LocalVectorService` | Local `pltt dev` service emulators and test fakes |
147
+ | `PlatformServiceUnavailable`, `UnavailablePlatformService` | Clear errors when an undeclared platform service is used |
148
+ | `LifecycleHooks` | Install/update/enable/disable/uninstall callbacks |
149
+ | `Event`, `subscribe_event(...)` | In-process platform event subscriptions |
150
+ | `sign_webhook(...)`, `verify_webhook_signature(...)` | HMAC-SHA256 webhook signing and verification |
151
+ | `ToolDefinition` | Base class for custom agent tools |
152
+ | `PluginManifest`, `load_manifest(...)` | Typed manifest parsing from `palette-plugin.json` |
153
+ | `SuccessResponse`, `ErrorResponse`, `PaginatedResponse` | Common response schemas for plugin APIs |
154
+ | `route_permission_issues(router, public_routes=None)` | Test helper that reports routes missing `require_permission(...)` |
155
+
128
156
  ## 5. Permissions
129
157
 
130
158
  Use route-level permission guards for normal APIs:
@@ -666,8 +694,6 @@ await ctx.redis.zrem("scores", "bob")
666
694
 
667
695
  await ctx.redis.enqueue("jobs", {"task": "sync"})
668
696
  await ctx.redis.dequeue("jobs")
669
- await ctx.redis.xadd("events", {"type": "created"})
670
- await ctx.redis.xread({"events": "0-0"}, count=10)
671
697
  await ctx.redis.lock("invoice:1", token, ttl=30)
672
698
  await ctx.redis.unlock("invoice:1", token)
673
699
  ```
@@ -747,12 +773,10 @@ Frontend code should call backend routes through the platform API helper, not by
747
773
  hardcoding backend origins.
748
774
 
749
775
  ```tsx
750
- import { createPaletteClient } from "@palettelab/sdk"
751
-
752
- const palette = createPaletteClient()
776
+ import { apiFetch } from "@palettelab/sdk"
753
777
 
754
778
  async function loadInvoices() {
755
- const res = await palette.apiFetch("/api/v1/plugins/finance-tools/invoices")
779
+ const res = await apiFetch("/api/v1/plugins/finance-tools/invoices")
756
780
  return res.json()
757
781
  }
758
782
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palettelab/cli",
3
- "version": "0.3.35",
3
+ "version": "0.3.36",
4
4
  "description": "Developer CLI for building Palette platform plugins — no platform source access required.",
5
5
  "bin": {
6
6
  "pltt": "bin/pltt.js"