# sugu

A metadata-driven application platform. One YAML document defines an application: its tables, fields and relations. Every environment generates a user interface and a REST API from that document.

> The YAML document is the product. To change what an application is you rewrite the document and a new version is created; there is no endpoint that adds a table or a field.

## Authentication

Every URL below needs an API key. Nothing else on this platform is public.

```
Authorization: Bearer sugu_<environment>_<secret>
```

A human creates the key in the console, under the application it belongs to. Keys cannot create keys, so an agent cannot mint its own credential or widen its own role.

## Start here

`GET https://www.sugu.es/api/v1/_me`

## Endpoints

The placeholders `{slug}` and `{env}` are filled in from the response to `_me`.

- `GET https://www.sugu.es/api/v1/_me`  
  Which application and environment this key belongs to, what its role may do, and a link to every document it may read. Call this first: the token embeds an environment id, not a slug, so no other URL can be constructed without it.
- `GET https://www.sugu.es/api/v1/_docs/metadata.md`  
  The YAML contract every application is written in: the options at each level, the field types, and a complete annotated example. Read this before proposing metadata. Also available as metadata.json.
- `GET https://www.sugu.es/api/v1/{slug}/{env}/_docs/agents.md`  
  A brief for the runtime API of one environment, filtered to what this key may call, in prose rather than schema. Explains the loops that OpenAPI cannot.
- `GET https://www.sugu.es/api/v1/{slug}/{env}/_docs/openapi.json`  
  OpenAPI 3.1 for the runtime API: the generated tables of one environment, as CRUD endpoints. Describes only what this key may call.
- `GET https://www.sugu.es/api/v1/{slug}/{env}/_meta/schema`  
  The generated schema of one environment — tables, fields, types and relations — as data rather than as an API description.
- `GET https://www.sugu.es/api/v1/{slug}/_admin/_docs/agents.md`  
  A brief for the backoffice API: reading and rewriting the metadata, versions, environments, backups and hooks. Filtered to this key, and it names what the key may not do as well as what it may.
- `GET https://www.sugu.es/api/v1/{slug}/_admin/_docs/openapi.json`  
  OpenAPI 3.1 for the backoffice API. Each operation carries x-capability, and x-environments where the capability is scoped to particular environments.

## Conventions

- Every response is {"data": …} or {"error": {"code", "message", …}}. The code is the contract; the message follows the reader's locale and must never be branched on.
- Sixty requests per minute per key, shared across both API surfaces. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining — pace yourself by those headers rather than by counting.
- The API is versioned in the path. Everything below is v1.

## Error codes

- **UNAUTHORIZED** (401) — The bearer token is missing, malformed or expired. Stop and ask a human for a new key; retrying will not help.
- **FORBIDDEN** (403) — This key may not perform this operation at all. Stop and report it rather than retrying.
- **FORBIDDEN_CAPABILITY** (403) — The key's role lacks a capability. The `capability` and `action` fields name it, and `environment` names where it was needed. Report exactly that to a human instead of retrying.
- **NOT_FOUND** (404) — The resource does not exist, or this key cannot see it. Re-read the parent collection before assuming it was deleted.
- **VALIDATION_FAILED** (422) — The payload does not satisfy the schema. Read `error.fields`, correct the named fields and send again.
- **FIELD_FORBIDDEN** (422) — One or more fields in the payload may not be written by this role. Remove them and resend; the remaining fields are still accepted.
- **INTEGRITY_VIOLATION** (409) — The operation breaks a required relation — usually a delete with dependants, or a reference to a record that does not exist. Resolve the relation first.
- **DEGRADED** (402) — The environment is degraded, normally for billing reasons. Nothing an agent can do; report it.
- **QUOTA_EXCEEDED** (402) — The account that owns this application has used up an allowance. `allowance` names which one, with `limit` and `used` beside it. There is nothing an agent can do: the owner has to wait for the period to renew, buy a budget reset, or upgrade the plan. Report it instead of retrying.
- **MAINTENANCE** (503) — A queued operation is rewriting this environment. Writes are refused until it finishes. Poll the environment until its status leaves `onderhoud`, then retry.
- **ENVIRONMENT_BUSY** (409) — Another operation already holds this environment. Wait for it rather than starting a second one.
- **METADATA_INVALID** (422) — The YAML is not a valid metadata document. `issues` carries a line, a code, a path and a message per problem; branch on `code`. Fix them and validate again before writing.
- **STALE_BASE_VERSION** (409) — Someone else wrote a new version since the one named in `base_version`. Re-read the metadata, reapply the change on top of it and send again — do not force.
- **OPERATION_FAILED** (500) — A queued operation failed. The reason is in the audit log, not in this response.
- **CONFLICT** (409) — The request contradicts the current state of the resource. Re-read it before deciding what to do.

## For humans

- https://www.sugu.es/
