@centia-io/mcp-server 1.0.16 → 1.0.17
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/AGENTS.md +72 -0
- package/package.json +4 -2
- package/skills/README.md +29 -0
- package/skills/centia-auth-model/SKILL.md +88 -0
- package/skills/centia-delivery/SKILL.md +74 -0
- package/skills/centia-feature/SKILL.md +50 -0
- package/skills/centia-file-import/SKILL.md +54 -0
- package/skills/centia-json-rpc/SKILL.md +86 -0
- package/skills/centia-keyvalue/SKILL.md +52 -0
- package/skills/centia-map-styling/SKILL.md +100 -0
- package/skills/centia-openapi-docs/SKILL.md +55 -0
- package/skills/centia-privileges/SKILL.md +66 -0
- package/skills/centia-provisioning/SKILL.md +105 -0
- package/skills/centia-realtime/SKILL.md +186 -0
- package/skills/centia-runtime-sdk/SKILL.md +98 -0
- package/skills/centia-types-formats/SKILL.md +74 -0
- package/skills/danish-search/SKILL.md +224 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# AGENT.md - Centia BaaS Core Rules
|
|
2
|
+
|
|
3
|
+
> Last updated: 2026-02-22
|
|
4
|
+
|
|
5
|
+
This file only contains global hard rules.
|
|
6
|
+
Task-specific guidance has been moved into `skills/*/SKILL.md`.
|
|
7
|
+
|
|
8
|
+
## 1) Prime Directive
|
|
9
|
+
|
|
10
|
+
- Prefer Centia MCP tools when available.
|
|
11
|
+
- Use `@centia-io/sdk` for all JS/TS runtime code.
|
|
12
|
+
- Use raw HTTP only for provisioning or SDK gaps.
|
|
13
|
+
- Never re-implement SDK functionality with `fetch`/`axios` in runtime app code.
|
|
14
|
+
|
|
15
|
+
## 2) Tool Priority (Hard Rule)
|
|
16
|
+
|
|
17
|
+
Use this order:
|
|
18
|
+
|
|
19
|
+
1. Centia MCP tools
|
|
20
|
+
2. `@centia-io/sdk`
|
|
21
|
+
3. OpenAPI-defined HTTP calls
|
|
22
|
+
4. Docs-backed HTTP calls
|
|
23
|
+
|
|
24
|
+
Never invent endpoints or payloads.
|
|
25
|
+
|
|
26
|
+
## 3) Runtime vs Provisioning (Hard Rule)
|
|
27
|
+
|
|
28
|
+
- Runtime application code must not perform schema provisioning.
|
|
29
|
+
- Schema changes are provisioning/codegen tasks only.
|
|
30
|
+
- Runtime apps must assume schema already exists.
|
|
31
|
+
|
|
32
|
+
## 4) Security and Auth Baselines
|
|
33
|
+
|
|
34
|
+
- Never hardcode credentials or tokens.
|
|
35
|
+
- Never commit secrets in `.env`.
|
|
36
|
+
- Frontend/browser code must not embed service tokens.
|
|
37
|
+
- Browser auth must use SDK OAuth flows; do not implement OAuth manually.
|
|
38
|
+
|
|
39
|
+
## 5) Destructive Operations Policy (Hard Rule)
|
|
40
|
+
|
|
41
|
+
Before destructive changes, present method/tool/purpose and require explicit user confirmation.
|
|
42
|
+
|
|
43
|
+
Destructive includes:
|
|
44
|
+
|
|
45
|
+
- `DROP`, `TRUNCATE`, destructive `DELETE`
|
|
46
|
+
- schema/table/column/constraint/index deletes
|
|
47
|
+
- policy overwrite operations
|
|
48
|
+
|
|
49
|
+
## 6) Required Skill Routing
|
|
50
|
+
|
|
51
|
+
Use the minimal matching skill(s) below for each task:
|
|
52
|
+
|
|
53
|
+
- Runtime SDK patterns: `skills/centia-runtime-sdk/SKILL.md`
|
|
54
|
+
- Provisioning and migrations: `skills/centia-provisioning/SKILL.md`
|
|
55
|
+
- JSON-RPC lifecycle and typed API: `skills/centia-json-rpc/SKILL.md`
|
|
56
|
+
- Auth model by runtime context: `skills/centia-auth-model/SKILL.md`
|
|
57
|
+
- PostgreSQL types and output formats: `skills/centia-types-formats/SKILL.md`
|
|
58
|
+
- Map view config and layer styling (classes/styles/labels): `skills/centia-map-styling/SKILL.md`
|
|
59
|
+
- Sub-user privileges and rights inheritance: `skills/centia-privileges/SKILL.md`
|
|
60
|
+
- Key/value store (app state, flags, preferences): `skills/centia-keyvalue/SKILL.md`
|
|
61
|
+
- Feature CRUD as GeoJSON by primary key: `skills/centia-feature/SKILL.md`
|
|
62
|
+
- Realtime WebSocket events: `skills/centia-realtime/SKILL.md`
|
|
63
|
+
- File import workflow: `skills/centia-file-import/SKILL.md`
|
|
64
|
+
- OpenAPI and docs fallback: `skills/centia-openapi-docs/SKILL.md`
|
|
65
|
+
- Delivery checklist and MCP reference: `skills/centia-delivery/SKILL.md`
|
|
66
|
+
- Danish address/matrikel search component: `skills/danish-search/SKILL.md`
|
|
67
|
+
|
|
68
|
+
## 7) Default Paths
|
|
69
|
+
|
|
70
|
+
- SDK client: `src/baas/client.ts`
|
|
71
|
+
- HTTP fallback layer: `src/baas/http.ts`
|
|
72
|
+
- Provisioning assets: `provision/`, `migrations/`, `schema/`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centia-io/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
|
-
"centia-api.json"
|
|
14
|
+
"centia-api.json",
|
|
15
|
+
"AGENTS.md",
|
|
16
|
+
"skills"
|
|
15
17
|
],
|
|
16
18
|
"scripts": {
|
|
17
19
|
"build": "tsc",
|
package/skills/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Skills Index
|
|
2
|
+
|
|
3
|
+
This folder contains task-specific skills referenced from `AGENT.md`.
|
|
4
|
+
|
|
5
|
+
## Quick Routing
|
|
6
|
+
|
|
7
|
+
Use the smallest matching skill set for the task.
|
|
8
|
+
|
|
9
|
+
| Skill | Use when |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `centia-runtime-sdk` | Building or refactoring JS/TS runtime code with `@centia-io/sdk` |
|
|
12
|
+
| `centia-provisioning` | Changing schema, tables, columns, constraints, indexes, policies, migrations |
|
|
13
|
+
| `centia-json-rpc` | Creating/updating/calling JSON-RPC methods and generating TypeScript interfaces |
|
|
14
|
+
| `centia-auth-model` | Implementing or reviewing auth across browser, backend, CLI, and provisioning |
|
|
15
|
+
| `centia-types-formats` | Choosing PostgreSQL types, casts, `type_hints`, `type_formats`, output formats |
|
|
16
|
+
| `centia-file-import` | Importing files with `postFileUpload` and `postFileProcess` |
|
|
17
|
+
| `centia-openapi-docs` | Using OpenAPI/docs as fallback when MCP/SDK are insufficient |
|
|
18
|
+
| `centia-map-styling` | Configuring map center/zoom/extent or layer cartography: classes, styles, labels |
|
|
19
|
+
| `centia-privileges` | Granting sub-user privileges, groups, rights inheritance, layer authentication levels |
|
|
20
|
+
| `centia-keyvalue` | Storing/reading JSON state (settings, flags, preferences) in the key/value store |
|
|
21
|
+
| `centia-feature` | Reading/creating/updating/deleting single features as GeoJSON by primary key |
|
|
22
|
+
| `centia-realtime` | Realtime WebSocket events, subscriptions with shapes, enabling table change events |
|
|
23
|
+
| `centia-delivery` | Final delivery checklist, MCP coverage check, and handoff quality gate |
|
|
24
|
+
| `danish-search` | Danish address/matrikel typeahead search component (`@centia-io/danish-search`) |
|
|
25
|
+
|
|
26
|
+
## Core Rule
|
|
27
|
+
|
|
28
|
+
Global hard rules stay in `AGENT.md`.
|
|
29
|
+
Task-specific workflows and references stay in `skills/*/SKILL.md`.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: centia-auth-model
|
|
3
|
+
description: Authentication policy for Centia BaaS across browser, backend, CLI, and provisioning contexts, including required SDK flows and environment variable usage.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Auth Model Policy
|
|
7
|
+
|
|
8
|
+
Use this skill whenever authentication is implemented or reviewed.
|
|
9
|
+
|
|
10
|
+
## Identify runtime context
|
|
11
|
+
|
|
12
|
+
Determine one of:
|
|
13
|
+
|
|
14
|
+
- browser app (SPA/frontend)
|
|
15
|
+
- server/backend/CLI
|
|
16
|
+
- provisioning script
|
|
17
|
+
|
|
18
|
+
## Browser apps
|
|
19
|
+
|
|
20
|
+
Use SDK OAuth PKCE flow only.
|
|
21
|
+
|
|
22
|
+
Required SDK classes:
|
|
23
|
+
|
|
24
|
+
- `CodeFlow` for sign-in/sign-out/callback handling
|
|
25
|
+
- `SignUp` for signup redirect flow
|
|
26
|
+
|
|
27
|
+
Forbidden:
|
|
28
|
+
|
|
29
|
+
- `CENTIA_ACCESS_TOKEN` in frontend code
|
|
30
|
+
- service tokens in browser app code
|
|
31
|
+
- manual OAuth implementation
|
|
32
|
+
- provisioning API calls from browser runtime
|
|
33
|
+
|
|
34
|
+
## Server and CLI
|
|
35
|
+
|
|
36
|
+
Allowed methods:
|
|
37
|
+
|
|
38
|
+
- `PasswordFlow`
|
|
39
|
+
- `CENTIA_ACCESS_TOKEN` for MCP/HTTP fallback
|
|
40
|
+
|
|
41
|
+
Typical use:
|
|
42
|
+
|
|
43
|
+
- provisioning
|
|
44
|
+
- admin/service-to-service operations
|
|
45
|
+
- CLI tools
|
|
46
|
+
|
|
47
|
+
## Provisioning scripts
|
|
48
|
+
|
|
49
|
+
Provisioning runs server-side only.
|
|
50
|
+
|
|
51
|
+
Allowed:
|
|
52
|
+
|
|
53
|
+
- access token
|
|
54
|
+
- `PasswordFlow`
|
|
55
|
+
- MCP tools
|
|
56
|
+
- OpenAPI calls
|
|
57
|
+
|
|
58
|
+
Forbidden:
|
|
59
|
+
|
|
60
|
+
- browser auth flows
|
|
61
|
+
|
|
62
|
+
## Responsibility matrix
|
|
63
|
+
|
|
64
|
+
- Browser app: `CodeFlow`
|
|
65
|
+
- Browser signup: `SignUp`
|
|
66
|
+
- Backend app: `PasswordFlow`
|
|
67
|
+
- Provisioning: `PasswordFlow` or access token
|
|
68
|
+
- CLI: `PasswordFlow`
|
|
69
|
+
|
|
70
|
+
## Environment variables
|
|
71
|
+
|
|
72
|
+
Server/provisioning:
|
|
73
|
+
|
|
74
|
+
- `CENTIA_HOST`
|
|
75
|
+
- `CENTIA_CLIENT_ID`
|
|
76
|
+
- `CENTIA_CLIENT_SECRET`
|
|
77
|
+
- `CENTIA_USERNAME`
|
|
78
|
+
- `CENTIA_PASSWORD`
|
|
79
|
+
- `CENTIA_DATABASE`
|
|
80
|
+
- optional: `CENTIA_ACCESS_TOKEN`
|
|
81
|
+
|
|
82
|
+
Browser (Vite):
|
|
83
|
+
|
|
84
|
+
- `VITE_CENTIA_HOST`
|
|
85
|
+
- `VITE_CENTIA_CLIENT_ID`
|
|
86
|
+
- `VITE_CENTIA_DATABASE`
|
|
87
|
+
|
|
88
|
+
Never commit secrets. Keep `.env.example` with placeholders.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: centia-delivery
|
|
3
|
+
description: Delivery and validation checklist for Centia tasks, including required output sections, MCP tool reference, geospatial mapping library selection, and final self-check criteria.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Delivery Checklist
|
|
7
|
+
|
|
8
|
+
Use this skill before finalizing Centia-related implementation work.
|
|
9
|
+
|
|
10
|
+
## Required delivery content
|
|
11
|
+
|
|
12
|
+
Include:
|
|
13
|
+
|
|
14
|
+
- setup steps
|
|
15
|
+
- env vars used
|
|
16
|
+
- install and run commands
|
|
17
|
+
- SDK usage explanation
|
|
18
|
+
- provisioning steps (if applicable)
|
|
19
|
+
- validation steps
|
|
20
|
+
- HTTP calls made (without secrets)
|
|
21
|
+
|
|
22
|
+
## MCP tool reference
|
|
23
|
+
|
|
24
|
+
Schema and tables:
|
|
25
|
+
|
|
26
|
+
- `getSchema`, `postSchema`, `patchSchema`, `deleteSchema`
|
|
27
|
+
- `getTable`, `postTable`, `patchTable`, `deleteTable`
|
|
28
|
+
- `getColumn`, `postColumn`, `patchColumn`, `deleteColumn`
|
|
29
|
+
- `getConstraint`, `postConstraint`, `deleteConstraint`
|
|
30
|
+
- `getIndex`, `postIndex`, `deleteIndex`
|
|
31
|
+
- `getSequence`, `postSequence`, `patchSequence`, `deleteSequence`
|
|
32
|
+
|
|
33
|
+
Query and API:
|
|
34
|
+
|
|
35
|
+
- `postSql`
|
|
36
|
+
- `postGraphQL`
|
|
37
|
+
- `getRpc`, `postRpc`, `patchRpc`, `deleteRpc`
|
|
38
|
+
- `postCall`, `postCallDry`, `getTypeScript`
|
|
39
|
+
|
|
40
|
+
Auth and access:
|
|
41
|
+
|
|
42
|
+
- `postOauth`, `postDevice`
|
|
43
|
+
- `getUser`, `postUser`, `patchUser`, `deleteUsers`
|
|
44
|
+
- `getRule`, `postRule`, `patchRule`, `deleteRule`
|
|
45
|
+
- `getPrivileges`, `patchPrivileges`
|
|
46
|
+
- `getClient`, `postClient`, `patchClient`, `deleteClient`
|
|
47
|
+
|
|
48
|
+
Metadata:
|
|
49
|
+
|
|
50
|
+
- `getMetaData`, `patchMetaData`
|
|
51
|
+
|
|
52
|
+
Import and misc:
|
|
53
|
+
|
|
54
|
+
- `postFileUpload`, `postFileProcess`
|
|
55
|
+
- `postCommit`
|
|
56
|
+
- `getStats`
|
|
57
|
+
|
|
58
|
+
## Mapping library selection
|
|
59
|
+
|
|
60
|
+
For map UIs:
|
|
61
|
+
|
|
62
|
+
- Default to MapLibre GL JS for straightforward map display and interaction.
|
|
63
|
+
- Use Leaflet or OpenLayers for advanced interaction or GIS-heavy needs.
|
|
64
|
+
- Prefer current docs lookup (for example Context7 MCP when available) before writing mapping code.
|
|
65
|
+
|
|
66
|
+
## Final self-check
|
|
67
|
+
|
|
68
|
+
- Used MCP tools where possible.
|
|
69
|
+
- Used SDK for runtime JS/TS.
|
|
70
|
+
- Kept provisioning separate from runtime.
|
|
71
|
+
- Avoided runtime schema changes.
|
|
72
|
+
- Used correct auth flow for context.
|
|
73
|
+
- Kept secrets out of source control.
|
|
74
|
+
- Followed OpenAPI/docs contract where HTTP was used.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: centia-feature
|
|
3
|
+
description: Use when reading, creating, updating, or deleting individual geographic features (rows) as GeoJSON by primary key in Centia BaaS tables, or when working with /api/v4/schemas/{schema}/tables/{table}/features endpoints, getFeature/postFeature/patchFeature/deleteFeature tools, the Features SDK class, WFS-T feature editing, or the srs/SRID of feature geometry.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Feature API (GeoJSON CRUD by primary key)
|
|
7
|
+
|
|
8
|
+
Use this skill for the v4 Feature API (`/api/v4/schemas/{schema}/tables/{table}/features/{feature}`): GeoJSON CRUD on single table rows, addressed by primary key, executed through the in-process WFS-T engine (versioning, workflow, geofence rules and tile-cache busting all apply). Successor of v2 `/api/v2/feature`.
|
|
9
|
+
|
|
10
|
+
## Availability
|
|
11
|
+
|
|
12
|
+
Lives on the GeoCloud2 branch `dev/multiple_styles` (commits `25900b64`…`844d8fd6`, 2026-08-25/26). As of 2026-08 it is **not** on production `api.centia.io` — assume dev-only. SDK support: `@centia-io/sdk` **>= 0.2.11** (published on npm; the `Features` class is absent in <= 0.2.10).
|
|
13
|
+
|
|
14
|
+
## Endpoints and semantics
|
|
15
|
+
|
|
16
|
+
**Token-only** (Bearer JWT on every request; there is NO anonymous read, even for public layers). Sub-users allowed, governed by per-table privileges (see `centia-privileges`). The table must be a registered layer with a **single-column primary key** (400 `NO_PRIMARY_KEY` otherwise) and WFS enabled (400 `WFS_NOT_ENABLED`).
|
|
17
|
+
|
|
18
|
+
| Operation | Route / MCP tool | Result |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| Get by key(s) | `GET .../features/{feature}` / `getFeature` — `{feature}` is one key **or a comma list** (`1,2,3`); `?srs` = output SRID (default 4326) | `200`: **one match → bare GeoJSON `Feature`; several → `FeatureCollection`**; `404` `FEATURE_NOT_FOUND` if none match (partial matches return `200` with the found ones) |
|
|
21
|
+
| Create | `POST .../features` (no key in path); body = `Feature` or `FeatureCollection`; `?srs` = SRID of incoming geometry / `postFeature` | `201` + `Location: .../features/{keys}` (comma list of the new keys — parse it for generated keys); `400` `NOTHING_INSERTED` if the layer is not editable |
|
|
22
|
+
| Update | `PATCH .../features/{feature}` (key optional) / `patchFeature` | `303 See Other` + `Location`; `404` `FEATURE_NOT_FOUND` if nothing updated |
|
|
23
|
+
| Delete | `DELETE .../features/{feature}` (one key **or a comma list**, like GET) / `deleteFeature` | `204`; `404` `FEATURE_NOT_FOUND` if nothing was deleted (partial matches delete the found ones → `204`) |
|
|
24
|
+
|
|
25
|
+
No PUT/upsert. No collection GET — reading a whole table is a SQL API or WFS job (`GET .../features` without a key → 400 `FEATURE_ID_REQUIRED`). Keys containing `'` are rejected (400 `INVALID_FEATURE_ID`).
|
|
26
|
+
|
|
27
|
+
## Body and write rules
|
|
28
|
+
|
|
29
|
+
- Body must be a GeoJSON `Feature` or a **non-empty** `FeatureCollection` (else 400 `INVALID_GEOJSON`). Geometry is optional — a feature without geometry inserts/updates properties only, and reads back with `geometry: null`.
|
|
30
|
+
- `srs` is asymmetric: output SRID on GET, **incoming**-geometry SRID on POST/PATCH, always defaulting to 4326 (GeoJSON lon/lat). Sending e.g. 25832 coordinates without `?srs=25832` stores garbage geometry.
|
|
31
|
+
- POST: a primary-key value in `properties` is used as the new key; otherwise one is generated. No upsert — posting an existing key fails the WFS transaction.
|
|
32
|
+
- PATCH: the path key wins; without it every feature must carry its primary key in `properties` (400 `PRIMARY_KEY_MISSING`). You **cannot PATCH one path key with a collection** (400 `INVALID_DATA`) — omit the key to batch-update. Omitted properties stay untouched.
|
|
33
|
+
- Property encoding (WFS-T): booleans become `t`/`f`, **JSON arrays are converted to PostgreSQL array literals automatically** — send plain JSON values, do not pre-format `"{1,2,3}"` strings.
|
|
34
|
+
|
|
35
|
+
## SDK (>= 0.2.11)
|
|
36
|
+
|
|
37
|
+
Standalone class **`Features`** (plural — `Feature` is the GeoJSON type), explicit-client pattern: `new Features(client.http)`. Methods: `getFeature<P>(schema, table, key | keys[], {srs?})` → `GeoJsonFeature<P> | GeoJsonFeatureCollection<P>` (union — normalize the shape yourself); `postFeature(schema, table, body, {srs?})` and `patchFeature(schema, table, body, {feature?, srs?})` → `{location}`; `deleteFeature(schema, table, key)`. Own minimal GeoJSON types (`GeoJsonFeature`, `GeoJsonFeatureCollection`, `GeoJsonGeometry`), no `@types/geojson`. Errors: `CentiaApiError` (`.status`/`.code`).
|
|
38
|
+
|
|
39
|
+
## Common mistakes
|
|
40
|
+
|
|
41
|
+
| Mistake | Reality |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Assuming production availability | dev/multiple_styles only; MCP tools need a server restart against the updated spec |
|
|
44
|
+
| Reading public layers without a token | v4 Feature API always requires a Bearer JWT (unlike the OGC routes) |
|
|
45
|
+
| Expecting one response shape from GET | one match = bare `Feature`, several = `FeatureCollection` |
|
|
46
|
+
| Listing a table via `GET .../features` | 400 `FEATURE_ID_REQUIRED` — use the SQL API or WFS for collections |
|
|
47
|
+
| Pre-formatting array columns as `"{a,b}"` strings | send JSON arrays; the server builds the PG array literal |
|
|
48
|
+
| PATCHing `/features/42` with a `FeatureCollection` | 400 `INVALID_DATA` — drop the path key and put keys in `properties` |
|
|
49
|
+
| Forgetting `?srs` on POST/PATCH of projected coordinates | geometry is read as EPSG:4326 by default |
|
|
50
|
+
| Expecting `200` from PATCH / a JSON body from POST | `303`/`201` with empty bodies; the keys are in the `Location` header |
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: centia-file-import
|
|
3
|
+
description: Two-step Centia file import workflow using MCP tools, covering upload, processing options, validation mode, geospatial projection settings, and supported input formats.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# File Import Workflow
|
|
7
|
+
|
|
8
|
+
Use this skill for importing tabular or geospatial files into Centia.
|
|
9
|
+
|
|
10
|
+
## Hard rule
|
|
11
|
+
|
|
12
|
+
Use MCP tools first:
|
|
13
|
+
|
|
14
|
+
1. `postFileUpload`
|
|
15
|
+
2. `postFileProcess`
|
|
16
|
+
|
|
17
|
+
Do not call raw HTTP import endpoints unless MCP is unavailable.
|
|
18
|
+
|
|
19
|
+
## Step 1: Upload
|
|
20
|
+
|
|
21
|
+
Call `postFileUpload` and capture returned file id/name.
|
|
22
|
+
|
|
23
|
+
## Step 2: Process
|
|
24
|
+
|
|
25
|
+
Call `postFileProcess` with uploaded file and target schema.
|
|
26
|
+
|
|
27
|
+
Key options:
|
|
28
|
+
|
|
29
|
+
- `import`: `false` for validation-only, `true` to commit
|
|
30
|
+
- `append`: append to existing table
|
|
31
|
+
- `truncate`: clear table before append
|
|
32
|
+
- `timestamp`: add timestamp column
|
|
33
|
+
- `s_srs` and `t_srs`: source/target projection fallback
|
|
34
|
+
- `p_multi`: promote single to multipart geometries
|
|
35
|
+
- `x_possible_names` and `y_possible_names`: CSV lon/lat hints
|
|
36
|
+
|
|
37
|
+
## Validation flow
|
|
38
|
+
|
|
39
|
+
Run with `import: false`, inspect response, then rerun with `import: true`.
|
|
40
|
+
|
|
41
|
+
## Supported formats
|
|
42
|
+
|
|
43
|
+
- GeoJSON (`.geojson`)
|
|
44
|
+
- Shapefile zip (`.zip` with sidecar files)
|
|
45
|
+
- GeoPackage (`.gpkg`)
|
|
46
|
+
- GML (`.gml`)
|
|
47
|
+
- CSV (`.csv`)
|
|
48
|
+
|
|
49
|
+
## Typical imported table shape
|
|
50
|
+
|
|
51
|
+
- primary key `gid`
|
|
52
|
+
- geometry column `the_geom`
|
|
53
|
+
- GiST index on `the_geom`
|
|
54
|
+
- inferred field types
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: centia-json-rpc
|
|
3
|
+
description: JSON-RPC method lifecycle for Centia BaaS, including method creation, invocation, dry-run type inference, TypeScript interface generation, and runtime usage with createApi or Rpc.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# JSON-RPC Workflow
|
|
7
|
+
|
|
8
|
+
Use this skill when creating, updating, testing, or calling Centia JSON-RPC methods.
|
|
9
|
+
|
|
10
|
+
## Purpose
|
|
11
|
+
|
|
12
|
+
JSON-RPC wraps SQL in named server-side methods for reuse, consistency, and central control.
|
|
13
|
+
|
|
14
|
+
## Define method (provisioning)
|
|
15
|
+
|
|
16
|
+
Use `postRpc`.
|
|
17
|
+
|
|
18
|
+
Parameter style:
|
|
19
|
+
|
|
20
|
+
- `:param`
|
|
21
|
+
- `:param::type` (required for type inference)
|
|
22
|
+
|
|
23
|
+
Example:
|
|
24
|
+
|
|
25
|
+
```txt
|
|
26
|
+
postRpc({
|
|
27
|
+
method: "addDays",
|
|
28
|
+
q: "select date(:date) + :days::int as result",
|
|
29
|
+
type_hints: { date: "timestamptz" },
|
|
30
|
+
type_formats: { result: "l jS F Y" }
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Manage definitions with:
|
|
35
|
+
|
|
36
|
+
- `getRpc`
|
|
37
|
+
- `postRpc`
|
|
38
|
+
- `patchRpc`
|
|
39
|
+
- `deleteRpc`
|
|
40
|
+
|
|
41
|
+
## Call method
|
|
42
|
+
|
|
43
|
+
Use `postCall` with JSON-RPC 2.0 envelope.
|
|
44
|
+
|
|
45
|
+
```txt
|
|
46
|
+
postCall({
|
|
47
|
+
jsonrpc: "2.0",
|
|
48
|
+
method: "addDays",
|
|
49
|
+
params: { date: "2025-05-01", days: 7 },
|
|
50
|
+
id: "1"
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- Omit `id` for notification mode.
|
|
55
|
+
- `params` can be object or array of objects for batch calls.
|
|
56
|
+
|
|
57
|
+
## Dry-run and TypeScript inference
|
|
58
|
+
|
|
59
|
+
1. Dry-run method with `postCallDry`.
|
|
60
|
+
2. Fetch generated interfaces with `getTypeScript`.
|
|
61
|
+
3. Save interface (for example `src/baas/api.ts`).
|
|
62
|
+
4. Use at runtime with `createApi<Api>()`.
|
|
63
|
+
|
|
64
|
+
Important: SQL params must include explicit casts (`:param::type`) to infer method signatures reliably.
|
|
65
|
+
|
|
66
|
+
## Runtime usage
|
|
67
|
+
|
|
68
|
+
Preferred typed call:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const api = createApi<Api>();
|
|
72
|
+
const rows = await api.getX({ x: 1 });
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Fallback generic call:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
await rpc.call({ jsonrpc: "2.0", method: "getX", params: { x: 1 }, id: 1 });
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Error codes to recognize
|
|
82
|
+
|
|
83
|
+
- `-32600` invalid request
|
|
84
|
+
- `-32601` method not found
|
|
85
|
+
- `-32602` invalid params
|
|
86
|
+
- `-32603` internal error
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: centia-keyvalue
|
|
3
|
+
description: Use when storing or reading small JSON state (app settings, feature flags, user preferences, drafts, snapshots) in the Centia BaaS key/value store, or when working with /api/v4/keyvalue endpoints, the Keyvalue SDK class, keys, owner/public flags, or paths projection.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Key/Value Store
|
|
7
|
+
|
|
8
|
+
Use this skill for the v4 Keyvalue API (`/api/v4/keyvalue/{key}`): per-database storage of arbitrary JSON under globally unique keys, with an owner/public access model.
|
|
9
|
+
|
|
10
|
+
## Availability
|
|
11
|
+
|
|
12
|
+
Lives on the GeoCloud2 branch `dev/multiple_styles` (commits `2213a099`, `3897be13`) and requires the v3 migration run (`GET /api/v3/admin/migrations` adds `owner`/`public` columns to `settings.key_value`). As of 2026-08 it is **not** confirmed on production `api.centia.io` — assume dev-only. SDK support: `@centia-io/sdk` **>= 0.2.10** (not 0.2.9). The legacy v2 `/api/v2/keyvalue` is unchanged and separate.
|
|
13
|
+
|
|
14
|
+
## Endpoints and semantics
|
|
15
|
+
|
|
16
|
+
Token-only (Bearer JWT on every request). Keys are **globally unique per database** — no schema namespacing, no format rules (SDK URL-encodes).
|
|
17
|
+
|
|
18
|
+
| Operation | Route / MCP tool | Result |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| List all visible keys | `GET /api/v4/keyvalue` / `getKeyvalue` (no key) | `200`, **plain JSON array** of entries (no wrapper) |
|
|
21
|
+
| Get one key | `GET /api/v4/keyvalue/{key}` | `200` entry; `404` `KEY_NOT_FOUND` if absent/not visible |
|
|
22
|
+
| Create | `POST .../{key}`, body `{value, public?}` / `postKeyvalue` | `201` + `Location`; `409` `KEY_EXISTS` if key exists |
|
|
23
|
+
| Update value and/or public | `PATCH .../{key}`, body `{value?, public?}` / `patchKeyvalue` | `303 See Other` + `Location` (see `centia-provisioning`) |
|
|
24
|
+
| Delete | `DELETE .../{key}` / `deleteKeyvalue` | `204`; `404` if absent/not owned |
|
|
25
|
+
|
|
26
|
+
Entry shape: `{id: int, key, value: <decoded JSON>, owner: string|null, public: bool}`. `value` is arbitrary JSON, required on POST — the spec declares `type: object`, but the server applies no type check, so scalars and arrays round-trip too. There is **no PUT/upsert**: create with POST, update with PATCH (on unknown state: POST, fall back to PATCH on 409). The `201`/`303` bodies are empty; their `Location` is `/api/v4/keyvalue/{key}` — GET it to read the entry back.
|
|
27
|
+
|
|
28
|
+
## Access model
|
|
29
|
+
|
|
30
|
+
- `owner` is **always set server-side from the JWT uid** — never send it in the body; ownership never changes.
|
|
31
|
+
- Super user: full CRUD on every key. Sub-user: reads own keys + `public: true` keys; creates/updates/deletes **only own** keys (violations surface as `404`, not `403`).
|
|
32
|
+
- Legacy rows with `owner IS NULL` are treated as public and super-owned: everyone reads, only the super user modifies.
|
|
33
|
+
|
|
34
|
+
## `paths` projection (GET single key only)
|
|
35
|
+
|
|
36
|
+
`GET .../{key}?paths=user.name,active` returns only the named sub-trees: comma separates paths, dot navigates; the result `value` is keyed by the path strings, e.g. `{"value": {"user.name": "Alice", "active": true}}`. Empty path or segment → `400` `INVALID_PATHS`. No other query params exist — **no `like`/`filter`** listing (that was v2 only); filter key names client-side.
|
|
37
|
+
|
|
38
|
+
## SDK (>= 0.2.10)
|
|
39
|
+
|
|
40
|
+
Standalone class, explicit-client pattern: `new Keyvalue(client.http)`. Methods `getKeyvalue()` (list) / `getKeyvalue<T>(key)` / `getKeyvalue(key, paths)` / `postKeyvalue<T>(key, {value, public?})` / `patchKeyvalue<T>(key, {value?, public?})` / `deleteKeyvalue(key)`; errors are `CentiaApiError` (`.status`/`.code`). Types: `KeyvalueEntry<T>`, `KeyvalueProjection`.
|
|
41
|
+
|
|
42
|
+
## Common mistakes
|
|
43
|
+
|
|
44
|
+
| Mistake | Reality |
|
|
45
|
+
|---|---|
|
|
46
|
+
| Assuming production availability | dev/multiple_styles + migration required; not confirmed on api.centia.io |
|
|
47
|
+
| PUT or POST to overwrite an existing key | No upsert; POST on existing key → `409` — use PATCH |
|
|
48
|
+
| Sending `owner` in the body | Owner comes from the JWT; body allows only `value` and `public` |
|
|
49
|
+
| `like=`/`filter=` query params on v4 | v2-only; v4 lists everything visible, filter client-side |
|
|
50
|
+
| Expecting `200` from PATCH | Returns `303 See Other` — disable auto-redirect |
|
|
51
|
+
| Expecting `403` when touching another user's key | Non-owned rows are invisible to writes → `404 KEY_NOT_FOUND` |
|
|
52
|
+
| Using `@centia-io/sdk` 0.2.9 for Keyvalue | The `Keyvalue` class ships in 0.2.10+ |
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: centia-map-styling
|
|
3
|
+
description: Map view configuration and layer cartography for Centia BaaS, including per-schema map center/zoom/extent, layers, classes, styles, and labels, MapServer-backed rendering, id round-trip rules, and payload value conventions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Map, Layers, Classes, Styles, and Labels
|
|
7
|
+
|
|
8
|
+
Use this skill when configuring the per-schema map view or the cartographic styling of layers (classes, styles, labels) via MCP tools or the v4 API.
|
|
9
|
+
|
|
10
|
+
## Availability
|
|
11
|
+
|
|
12
|
+
The Map API and the granular class/style/label sub-routes live on the GeoCloud2 branch `dev/multiple_styles`. As of 2026-08 they are **not** on production `api.centia.io`. SDK support: `@centia-io/sdk` >= 0.2.5 has `provisioning.maps.getMap/patchMap` and the `MapConfig` type.
|
|
13
|
+
|
|
14
|
+
## Data model
|
|
15
|
+
|
|
16
|
+
```txt
|
|
17
|
+
Map per-SCHEMA view config (center, zoom, extent) — orthogonal to layers
|
|
18
|
+
Layer one relation, key = schema.table.geometry_column, carries `properties` (def JSON)
|
|
19
|
+
└─ classes[] one rendering rule each: expression + scale range + sortid
|
|
20
|
+
├─ styles[] one symbolizer each (MapServer STYLE parameters)
|
|
21
|
+
└─ labels[] one text label each (MapServer LABEL parameters)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Classes, styles, and labels are converted server-side into a MapServer mapfile; they control WMS/tile rendering. The schema's Map `extent` is also used as the schema bbox in OGC GetCapabilities.
|
|
25
|
+
|
|
26
|
+
## Map view config
|
|
27
|
+
|
|
28
|
+
- `GET`/`PATCH /api/v4/map/schema/{schema}` — MCP tools `getMap` / `patchMap`.
|
|
29
|
+
- Shape: `{ center: [lon, lat] | null, zoom: number | null, extent: [minx, miny, maxx, maxy] | null }`.
|
|
30
|
+
- **CRS is EPSG:4326** (lon/lat). Older copies of the OpenAPI spec say EPSG:3857 — that is outdated; the API surface transforms to/from the 3857 storage at the boundary.
|
|
31
|
+
- PATCH is partial: only provided keys are updated; explicit `null` clears a key. Returns `303 See Other` (see `centia-provisioning` for redirect handling).
|
|
32
|
+
|
|
33
|
+
## Layer endpoints — two edit models
|
|
34
|
+
|
|
35
|
+
| Model | Route / MCP tool | Semantics |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| Atomic configure | `POST /api/v4/layers` / `postLayer` | Sets `properties` and **replaces the entire `classes` array** |
|
|
38
|
+
| Layer properties | `PATCH /api/v4/layers/{layer}` / `patchLayer` | Key-merge on the def JSON only (no classes) |
|
|
39
|
+
| Granular create | `POST .../classes`, `.../styles`, `.../labels` / `postLayerClass`, `postStyle`, `postLabel` | Additive; body is one object or an array |
|
|
40
|
+
| Granular update | `PATCH .../classes/{id}`, etc. / `patchLayerClass`, `patchStyle`, `patchLabel` | Key-merge on that entry |
|
|
41
|
+
| Granular delete | `DELETE .../{id}` / `deleteLayerClass`, `deleteStyle`, `deleteLabel` | `{id}` accepts comma-separated ids |
|
|
42
|
+
|
|
43
|
+
`POST /api/v4/layers` configures **existing** layers (relations already registered); it does not create tables. Preferred bulk workflow: `getLayer` → edit the document locally → one atomic `postLayer`.
|
|
44
|
+
|
|
45
|
+
## Id and round-trip rules
|
|
46
|
+
|
|
47
|
+
- Ids on classes, styles, and labels are fixed, server-assigned (8 hex chars). Send **new** entries *without* `id` — a client-supplied id on class creation is rejected with 400.
|
|
48
|
+
- When using atomic `postLayer`, send **existing ids back unchanged**; entries arriving without id are treated as new and get freshly minted ids (identity cannot be guessed).
|
|
49
|
+
- Round-trip unknown keys untouched: legacy classes can carry flat label keys (e.g. a top-level `force`). Do not strip them.
|
|
50
|
+
|
|
51
|
+
## Value conventions
|
|
52
|
+
|
|
53
|
+
- Numeric fields are **strings**; empty string `''` means unset. `sortid` is a real integer (convention: steps of 10; defaults to highest existing + 10).
|
|
54
|
+
- Colors are hex `#RRGGBB`. Opacity is `'0'`–`'100'`.
|
|
55
|
+
- Many style/label numeric fields accept a `[column]` reference for data-driven values (size, angle, offsets).
|
|
56
|
+
|
|
57
|
+
## Class expressions and label text
|
|
58
|
+
|
|
59
|
+
- Do **not** use the layer properties `theme_column` (CLASSITEM) and `label_column` (LABELITEM). They are the legacy mechanism and must not be combined with class expressions / label `text` — leave both empty (`''`).
|
|
60
|
+
- Classify with a standalone logical MapServer `expression` on each class, and label with the label's `text` expression (e.g. `[name]`).
|
|
61
|
+
- Quoting in class expressions depends on the column type:
|
|
62
|
+
- **String columns:** quote *both* sides, including the `[column]` reference: `'[Status]'='Forslag'` (`'string'='string'`).
|
|
63
|
+
- **Numeric columns:** no quotes on either side: `[tal]=1` (`1=1`).
|
|
64
|
+
|
|
65
|
+
## Enum quick reference
|
|
66
|
+
|
|
67
|
+
| Field | Values |
|
|
68
|
+
|---|---|
|
|
69
|
+
| style `linecap` | `round` `butt` `square` |
|
|
70
|
+
| style `geomtransform` | `bbox` `centroid` `end` `labelpnt` `labelpoly` `start` `vertices` |
|
|
71
|
+
| style `symbol` (built-ins) | `circle` `square` `triangle` `hatch1` `dashed1` `dot-dot` `dashed-line-short` `dashed-line-long` `dash-dot` `dash-dot-dot` `arrow` `arrow2` |
|
|
72
|
+
| label `position` | `auto` `ul` `uc` `ur` `cl` `cc` `cr` `ll` `lc` `lr` |
|
|
73
|
+
| label `angle` keywords | numeric, `auto`, `auto2`, `follow`, or `[column]` |
|
|
74
|
+
| label `fontweight` | `normal` `bold` `italic` `bolditalic` |
|
|
75
|
+
| layer `geotype` | `Default` `POINT` `LINE` `POLYGON` |
|
|
76
|
+
| layer `format` | `PNG` `jpeg_low` `jpeg_medium` `jpeg_high` |
|
|
77
|
+
| layer `cache` | `disk` `sqlite` `s3` `memcache` |
|
|
78
|
+
|
|
79
|
+
## Scale gates (all "Numeric value stored as a string")
|
|
80
|
+
|
|
81
|
+
`minscaledenom`/`maxscaledenom` exist at layer, class, and label level; layer-level `label_min_scale`/`label_max_scale` gate all labels. Min = most-zoomed-in bound, max = most-zoomed-out bound.
|
|
82
|
+
|
|
83
|
+
## Common mistakes
|
|
84
|
+
|
|
85
|
+
| Mistake | Reality |
|
|
86
|
+
|---|---|
|
|
87
|
+
| Sending map `center`/`extent` in EPSG:3857 | The surface is EPSG:4326 (lon/lat); 3857 in old spec copies is wrong |
|
|
88
|
+
| `postLayer` without existing class/style/label ids | Whole `classes` array is replaced; missing ids are re-minted, breaking references |
|
|
89
|
+
| Client-generated ids on new entries | Server assigns ids; class creation with an id returns 400 |
|
|
90
|
+
| Numeric values as JSON numbers | Most def/class/style/label numerics are strings; `''` = unset |
|
|
91
|
+
| Adding a class via `PATCH /layers/{layer}` | That route key-merges layer properties only; use `postLayerClass` or atomic `postLayer` |
|
|
92
|
+
| Stripping unrecognized keys before writing back | Legacy flat keys must round-trip unchanged |
|
|
93
|
+
| Setting `theme_column`/`label_column` alongside class expressions or label `text` | The two mechanisms must not be combined — leave both properties empty and use expressions/`text` |
|
|
94
|
+
| String expression written `[Status]='Forslag'` | Quote the column reference too for string columns: `'[Status]'='Forslag'`; numeric columns stay unquoted: `[tal]=1` |
|
|
95
|
+
|
|
96
|
+
## WMS preview
|
|
97
|
+
|
|
98
|
+
Preview rendering with `GET /api/v4/ows/schema/{schema}/database/{database}?SERVICE=WMS&...&LAYERS={schema}.{table}`. Since GC2 `cd168572` (`dev/multiple_styles`) this single endpoint serves Bearer, HTTP Basic, and anonymous clients; the old token-only route `/api/v4/ows/schema/{schema}` is **removed**. A Bearer token must match `{database}` — a mismatch returns 401 (OGC ServiceException), never a silent downgrade to anonymous. Binary GetMap responses are a documented SDK gap — use raw HTTP there (see `centia-runtime-sdk` for the fallback boundary).
|
|
99
|
+
|
|
100
|
+
Access control for layers and OWS is covered in `centia-privileges`.
|