Feat v0.7.4 docs surface work (#58)
All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-frontend (push) Successful in 5s
CI/CD / test-go-pg (push) Successful in 2m51s
CI/CD / test-sqlite (push) Successful in 2m51s
CI/CD / build-and-deploy (push) Successful in 39s
All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-frontend (push) Successful in 5s
CI/CD / test-go-pg (push) Successful in 2m51s
CI/CD / test-sqlite (push) Successful in 2m51s
CI/CD / build-and-deploy (push) Successful in 39s
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #58.
This commit is contained in:
@@ -79,6 +79,7 @@ Every package has a `manifest.json` at its root. Example for a surface:
|
||||
| `settings` | no | User-configurable settings schema |
|
||||
| `exports` | libraries | Functions exported for other packages |
|
||||
| `hooks` | no | Event bus subscriptions |
|
||||
| `config_section` | no | Settings/Admin panel injection (see below) |
|
||||
| `schema_version` | no | Integer for additive schema migrations |
|
||||
|
||||
## db_tables Schema
|
||||
@@ -138,24 +139,73 @@ Only `path` and `method` are required. All other fields are optional. Malformed
|
||||
|
||||
## Starlark Sandbox API
|
||||
|
||||
Starlark scripts run server-side with a CPU budget and memory ceiling. Available modules (granted per-permission by admin):
|
||||
Starlark scripts run server-side with a 1M operation budget and no
|
||||
filesystem access. See the [Starlark Reference](STARLARK-REFERENCE) for
|
||||
the complete module catalog, function signatures, and permission gates.
|
||||
|
||||
| Module | Permission | API |
|
||||
|--------|-----------|-----|
|
||||
| `db` | `db.write` | `db.query(table, filters)`, `db.insert(table, row)`, `db.update(table, id, row)`, `db.delete(table, id)` |
|
||||
| `http` | `http` | `http.get(url)`, `http.post(url, body)` -- SSRF-safe, no private IPs by default |
|
||||
| `notifications` | `notifications` | `notifications.send(user_id, title, body)` |
|
||||
| `secrets` | `secrets` | `secrets.get(connection_type)` -- reads from the credential vault |
|
||||
| `api` | (implicit) | Registers HTTP routes at `/s/:slug/api/*path` |
|
||||
| `realtime` | `realtime.publish` | `realtime.publish(channel, event, data)` -- push to WebSocket clients |
|
||||
## config_section — Settings Panel Injection
|
||||
|
||||
The sandbox cannot spawn goroutines, access the filesystem, or import arbitrary packages.
|
||||
Packages can inject configuration panels into the Settings, Admin, or
|
||||
Team Admin surfaces. Declare `config_section` in `manifest.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"config_section": {
|
||||
"label": "My Config",
|
||||
"icon": "M12 2L2 7l10 5 10-5-10-5z",
|
||||
"component": "js/config.js",
|
||||
"surfaces": ["settings", "admin"],
|
||||
"category": "system"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `label` | yes | Navigation label shown in the sidebar or tab list |
|
||||
| `icon` | no | SVG path data for the nav icon |
|
||||
| `component` | no | JS asset path (default: `js/config.js`). Must `export default` a Preact component. |
|
||||
| `surfaces` | yes | Target surfaces: `"settings"`, `"admin"`, `"team-admin"` |
|
||||
| `category` | no | Admin surface category tab (default: `"system"`). Ignored for settings/team-admin. |
|
||||
|
||||
**How it works:**
|
||||
|
||||
1. At page load, the backend scans all enabled packages for `config_section`
|
||||
entries targeting the current surface.
|
||||
2. Matching sections are injected into the page as `__CONFIG_SECTIONS__`.
|
||||
3. The frontend dynamically imports the component module and renders it
|
||||
as an additional tab/section.
|
||||
4. The component receives `{ packageId, teamId }` as props.
|
||||
|
||||
**Example component** (`js/config.js`):
|
||||
|
||||
```javascript
|
||||
const { html } = window;
|
||||
const { useState, useEffect } = hooks;
|
||||
|
||||
export default function MyConfig({ packageId }) {
|
||||
const [val, setVal] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
sw.api.ext(packageId).get('/settings').then(r => setVal(r.value));
|
||||
}, []);
|
||||
|
||||
return html`<div>
|
||||
<label>API Key</label>
|
||||
<input value=${val} onInput=${e => setVal(e.target.value)} />
|
||||
<button onClick=${() => sw.api.ext(packageId).put('/settings', { value: val })}>Save</button>
|
||||
</div>`;
|
||||
}
|
||||
```
|
||||
|
||||
## Permissions Model
|
||||
|
||||
Extensions declare required permissions in `manifest.json`. The admin must grant each permission before the extension can use the corresponding module. Permission status is visible in Admin > Packages > Permissions.
|
||||
Extensions declare required permissions in `manifest.json`. The admin
|
||||
must grant each permission before the extension can use the corresponding
|
||||
sandbox module. Permission status is visible in **Admin > Packages > Permissions**.
|
||||
|
||||
Kernel permissions for users/groups: `extension.use`, `extension.install`, `workflow.create`, `workflow.submit`, `admin.view`, `token.unlimited`.
|
||||
See [Permissions & Groups](PERMISSIONS-AND-GROUPS) for the full RBAC
|
||||
model, user permission slugs, and settings cascade.
|
||||
|
||||
## File Structure
|
||||
|
||||
|
||||
Reference in New Issue
Block a user