Changeset 0.38.1 (#234)

Co-authored-by: gobha <jasafpro@gmail.com>
Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
2026-03-25 11:13:12 +00:00
committed by xcaliber
parent 10acadc9d0
commit 6943c91f40
30 changed files with 2410 additions and 10 deletions

View File

@@ -337,6 +337,83 @@ to disk.
- `400``starlark package missing entry point "script.star"` (or
custom `entry_point` value)
## 5. Extension Connections (v0.38.1)
Scoped credential management for extensions that integrate with
external services. Same scope/resolution pattern as provider configs
(personal → team → global).
### Personal Connections
**Auth:** Authenticated user
```
GET /connections → {"data": [...connection summaries]}
POST /connections ← {"type","package_id","name","config"} → {"id","type","name"}
GET /connections/:id → connection summary (owned only)
PUT /connections/:id ← {"name?","config?"} → {"message":"connection updated"}
DELETE /connections/:id → {"message":"connection deleted"}
GET /connections/resolve → resolved connection (decrypted config)
?type=gitea&name=Work+Gitea
```
### Team Connections
**Auth:** Team admin (RequireTeamAdmin middleware)
```
GET /teams/:teamId/connections → {"data": [...connection summaries]}
POST /teams/:teamId/connections ← {"type","package_id","name","config"} → {"id","type","name"}
PUT /teams/:teamId/connections/:id ← {"name?","config?"} → {"message":"connection updated"}
DELETE /teams/:teamId/connections/:id → {"message":"connection deleted"}
```
### Admin (Global) Connections
**Auth:** Admin
```
GET /admin/connections → {"data": [...connection summaries]}
POST /admin/connections ← {"type","package_id","name","config"} → {"id","type","name"}
PUT /admin/connections/:id ← {"name?","config?"} → {"message":"connection updated"}
DELETE /admin/connections/:id → {"message":"connection deleted"}
```
**Connection summary** (list/get responses — secrets masked):
```json
{
"id": "uuid", "type": "gitea", "package_id": "git-board",
"scope": "personal", "name": "Work Gitea",
"is_active": true, "has_config": true,
"created_at": "2026-03-25T...", "updated_at": "2026-03-25T..."
}
```
**Scope resolution:** `GET /connections/resolve?type=gitea` resolves
via personal → team → global chain. Returns full connection with
decrypted config. Optional `name` parameter for named resolution.
**Config encryption:** Fields with `type: "secret"` in the package
manifest's `connections[].fields` are encrypted at rest using the
same vault pattern as provider API keys. The handler layer encrypts
on write and decrypts on read. The store is encryption-agnostic.
**Unique constraint:** `(type, scope, owner_id, name)` — a user cannot
have two connections of the same type with the same name.
**Starlark module:** Extensions with `connections.read` permission
get a `connections` module:
```python
conn = connections.get("gitea") # scope chain
conn = connections.get("gitea", name="Work Gitea") # named
all = connections.list("gitea") # all accessible
```
Each returned dict contains `id`, `type`, `name`, `scope` plus all
config fields with secrets decrypted.
---
### Builtin Seeding
On startup, `SeedBuiltinExtensions()` scans `extensions/builtin/`