Changeset 0.38.1 (#234)
Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
@@ -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/`
|
||||
|
||||
Reference in New Issue
Block a user