Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions skills/objectstack-platform/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ export default defineStack({
### Full Configuration Reference

`defineStack()` accepts an `ObjectStackDefinitionInput`. Each top-level key
holds a collection of one metadata kind — `manifest`, `objects`,
`objectExtensions`, `views`, `apps`, `pages`, `dashboards`,
`reports`, `datasets`, `actions`, `flows`, `jobs`,
`emailTemplates`, `docs`, `books`, `positions`, `permissions`,
`capabilities`, `sharingRules`, `apis`, `webhooks`, `api`, `agents`,
`tools`, `skills`, `hooks`, `functions`, `mappings`, `analyticsCubes`,
`connectors`, `data` (seed), `datasources`, `datasourceMapping`,
`translations`, `i18n`, `plugins`, `devPlugins`, `requires`, `tiers`.
holds one metadata kind — `manifest`, `objects`, `objectExtensions`,
`views`, `apps`, `pages`, `dashboards`, `reports`, `datasets`,
`actions`, `flows`, `jobs`, `emailTemplates`, `docs`, `books`,
`positions`, `permissions`, `capabilities`, `sharingRules`, `apis`,
`webhooks`, `api`, `server`, `agents`, `tools`, `skills`, `hooks`,
`functions`, `mappings`, `analyticsCubes`, `connectors`, `data` (seed),
`datasources`, `datasourceMapping`, `translations`, `i18n`, `plugins`,
`devPlugins`, `requires`, `tiers`.

There is deliberately **no** top-level `workflows` or `approvals` collection:
an approval is authored as a flow with Approval nodes (ADR-0019), and record
Expand Down Expand Up @@ -315,7 +315,7 @@ manifest: {
}
```

**Object naming:** The object `name` is the canonical identifier and equals the physical table name. Embed any domain prefix directly in the name (e.g. `name: 'crm_account'`); the object-level `namespace` *field* is deprecated and ignored by the runtime.
**Object naming:** The object `name` is the canonical identifier and equals the physical table name. Embed any domain prefix directly in the name (e.g. `name: 'crm_account'`); the object-level `namespace` *field* is retired (ADR-0129 D3) and refused at load.

**`manifest.namespace` (ADR-0048):** Optional, but **enforced once set**. When a package declares `manifest.namespace: 'crm'`, every `object.name` must start with `crm_` or `defineStack` errors (`validateNamespacePrefix` in `@objectstack/spec`); the legacy `<ns>__<short>` double-underscore form is rejected, and `sys_`-prefixed names are platform-reserved and exempt. The namespace is also a package-ownership key — installing two packages that both claim `crm` fails with `NamespaceConflictError` (downgrade to a warning with `OS_METADATA_COLLISION=warn`). `os lint` additionally emits a non-fatal `naming/namespace-prefix` warning for bare-named UI/automation items (app, page, dashboard, flow, action, report, dataset) when a namespace is set.

Expand Down Expand Up @@ -576,7 +576,7 @@ PORT=8080 os start # production — pin the port explicitly (see Ports & netwo

A minimal but complete project from scratch:

**`package.json`** (mirrors the `blank` template):
**`package.json`**:
```json
{
"name": "my-todo-app",
Expand All @@ -588,13 +588,13 @@ A minimal but complete project from scratch:
"validate": "objectstack validate"
},
"dependencies": {
"@objectstack/spec": "^16.0.0-rc.1",
"@objectstack/runtime": "^16.0.0-rc.1",
"@objectstack/driver-memory": "^16.0.0-rc.1",
"@objectstack/plugin-hono-server": "^16.0.0-rc.1"
"@objectstack/spec": "^17.0.0",
"@objectstack/runtime": "^17.0.0",
"@objectstack/driver-memory": "^17.0.0",
"@objectstack/plugin-hono-server": "^17.0.0"
},
"devDependencies": {
"@objectstack/cli": "^16.0.0-rc.1",
"@objectstack/cli": "^17.0.0",
"typescript": "^6.0.0"
}
}
Expand Down Expand Up @@ -741,7 +741,7 @@ import { ObjectKernel } from '@objectstack/core';

const kernel = new ObjectKernel({
logger: {
level: 'info', // 'debug' | 'info' | 'warn' | 'error' | 'fatal'
level: 'info', // debug|info|warn|error|fatal|silent
format: 'json', // 'json' | 'text' | 'pretty'
},
defaultStartupTimeout: 30000, // Per plugin (ms)
Expand Down Expand Up @@ -772,7 +772,7 @@ import type { Plugin, PluginContext } from '@objectstack/core';
export interface Plugin {
name: string; // Unique identifier (reverse domain recommended)
version?: string; // Semantic version
type?: string; // 'standard' | 'ui' | 'driver' | 'server' | 'app'
type?: string; // standard|ui|driver|server|app|theme|agent|objectql
dependencies?: string[]; // Plugins that must init before this one

// Phase 1: Register services
Expand Down
2 changes: 1 addition & 1 deletion skills/objectstack-platform/rules/plugin-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export interface Plugin {
version?: string;

/** Plugin type */
type?: string; // 'standard' | 'ui' | 'driver' | 'server' | 'app' | 'theme' | 'agent'
type?: string; // standard|ui|driver|server|app|theme|agent|objectql

/** Plugins that must init before this one */
dependencies?: string[];
Expand Down
12 changes: 6 additions & 6 deletions skills/objectstack-platform/rules/service-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,34 +158,34 @@ The REST plugin (`com.objectstack.rest.api`, `@objectstack/rest`) registers

## Core Fallback Injection

ObjectKernel auto-injects in-memory fallbacks for `core`-criticality services not registered by any plugin during Phase 1.
ObjectKernel auto-injects an in-memory fallback for each `core` service that has one and no plugin registered in Phase 1.

```
Phase 1: init() completes for all plugins
Kernel checks ServiceRequirementDef (@objectstack/spec/system):
'data' → required → ERROR if missing (no fallback; ObjectQLPlugin registers it)
'data' → required → ERROR if missing (ObjectQLPlugin registers it)
'metadata' → core → auto-inject createMemoryMetadata() if missing
'cache' → core → auto-inject createMemoryCache() if missing
'queue' → core → auto-inject createMemoryQueue() if missing
'job' → core → auto-inject createMemoryJob() if missing
'job' → core → NO fallback — warns; getService throws if missing
'i18n' → core → auto-inject createMemoryI18n() if missing
'auth' → core → no fallback factory — degraded-capability warning if missing
'auth' → core → NO fallback — warns; getService throws if missing
'realtime' → optional → skip, plugins should check availability
Phase 2: start() begins — all core services available
```

The fallbacks are **factories** exported from `@objectstack/core`
(`createMemoryCache`, `createMemoryMetadata`, `createMemoryQueue`,
`createMemoryJob`, `createMemoryI18n`) — not classes.
`createMemoryI18n`) — not classes; `job`/`auth` have none.

### Service Criticality Levels

| Level | Behavior |
|:------|:---------|
| `required` | Kernel throws if missing — system cannot start |
| `core` | Auto-injected in-memory fallback if no plugin provides it |
| `core` | In-memory fallback auto-injected where one exists, else warn |
| `optional` | Silently skipped — plugins must check before use |

## Incorrect vs Correct
Expand Down
Loading