@owlmeans/api-config-server 0.1.18-rc.17 → 0.1.18-rc.18
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/README.md +4 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/api-config-server/SKILL.md +13 -26
- package/build/actions/config.d.ts.map +1 -1
- package/build/actions/config.js +2 -30
- package/build/actions/config.js.map +1 -1
- package/package.json +5 -5
- package/src/actions/config.ts +2 -44
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Server-side entrypoint that serves safe configuration values at `GET /assets/con
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
- Registers the `API_CONFIG` handler that returns
|
|
7
|
+
- Registers the `API_CONFIG` handler that returns package-allowlisted config fields to clients
|
|
8
8
|
- Used alongside `@owlmeans/api-config-client` to push runtime config from server to browser
|
|
9
9
|
- Include `entrypoints` in your server entrypoint registration
|
|
10
10
|
|
|
@@ -28,6 +28,8 @@ context.registerEntrypoints([...appEntrypoints, ...apiConfigEntrypoints])
|
|
|
28
28
|
### `entrypoints`
|
|
29
29
|
|
|
30
30
|
Array of server-side route handlers for the config advertisement endpoint (`GET /assets/config.json`).
|
|
31
|
+
The handler returns only values registered through `apiConfigPlugin()` by packages loaded in the
|
|
32
|
+
server process; it never copies server config generically.
|
|
31
33
|
|
|
32
34
|
## Related Packages
|
|
33
35
|
|
|
@@ -42,7 +44,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
42
44
|
your project's skill store (`.agents/skills/`):
|
|
43
45
|
|
|
44
46
|
```sh
|
|
45
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
47
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.13
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/api-config-server",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-09-
|
|
4
|
+
"version": "0.1.18-rc.18",
|
|
5
|
+
"generatedAt": "2026-09-10T18:54:42.492Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: api-config-server
|
|
3
|
-
description: How to use @owlmeans/api-config-server — the backend half of the runtime config flow, which answers the api-config endpoint
|
|
3
|
+
description: How to use @owlmeans/api-config-server — the backend half of the runtime config flow, which answers the api-config endpoint from package-owned allowlist plugins. Auto-invoked when serving API config from a server app or deciding what a backend advertises to its clients.
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
@@ -8,7 +8,7 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/api-config-server
|
|
9
9
|
|
|
10
10
|
**Layer:** Server
|
|
11
|
-
**Install:** `"@owlmeans/api-config-server": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/api-config-server": "^0.1.18-rc.18"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
Answers the declaration shared by `@owlmeans/api-config`; the browser side that consumes it is
|
|
14
14
|
`@owlmeans/api-config-client`.
|
|
@@ -31,30 +31,17 @@ include this one, so spreading those is enough and adding this list again is red
|
|
|
31
31
|
|
|
32
32
|
## What is advertised
|
|
33
33
|
|
|
34
|
-
The handler
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`secret` and `apiClientId` stripped, and providers marked `internal` dropped entirely.
|
|
46
|
-
- Every remaining config key is copied verbatim, except `debug`, `services`, `plugins` and the keys
|
|
47
|
-
in `notAdvertizedConfigKeys` (`dbs`, `trusted`, `ready`, `service`, `type`, `records`,
|
|
48
|
-
`webService`, `oidc`, `storageBuckets`, `secrets`). The answer is assembled in three layers — the
|
|
49
|
-
seeded keys above, then that verbatim copy, then the conditional `oidc` rebuild — so the verbatim
|
|
50
|
-
copy overwrites whichever seeded key it also carries. `brand` is on neither exclusion list, so it
|
|
51
|
-
is carried, and the server's own brand settings are what the client receives; the `{}` the handler
|
|
52
|
-
seeds survives only for a server that declares no brand at all.
|
|
53
|
-
|
|
54
|
-
The consequence is the rule to work by: **a backend config key is public unless a list says
|
|
55
|
-
otherwise.** Adding a credential, a connection string or an internal address to the config means
|
|
56
|
-
adding its key to `notAdvertizedConfigKeys` in `@owlmeans/api-config` in the same change; adding a
|
|
57
|
-
config-record type means listing it in `allowedConfigRecords` before a client can see it.
|
|
34
|
+
The handler calls `advertisedConfig(ctx.cfg)`. It copies nothing generically: only import-time
|
|
35
|
+
`apiConfigPlugin()` registrations from `@owlmeans/api-config` and packages the application loaded
|
|
36
|
+
can contribute fields.
|
|
37
|
+
|
|
38
|
+
- Base registration keeps public service routes, branding, login settings, selected debug flags and frontend plugins. An `sservice()` route with only `internalHost`/`internalPort` is omitted rather than re-exposed through its derived `host`/`port`.
|
|
39
|
+
- `@owlmeans/oidc` admits only browser OIDC fields and drops internal providers and credentials.
|
|
40
|
+
- `@owlmeans/flow`, `@owlmeans/i18n` and `@owlmeans/payment` register their own client settings and record types.
|
|
41
|
+
- SMTP, queues, databases, storage, trusted keys, secrets and all unregistered config fields are absent.
|
|
42
|
+
|
|
43
|
+
The endpoint carries no guard — it is fetched before the client has any credential — so nothing
|
|
44
|
+
that requires authorization to read belongs in a plugin's `allow` selection.
|
|
58
45
|
|
|
59
46
|
The endpoint carries no guard — it is fetched before the client has any credential — so nothing
|
|
60
47
|
that requires authorization to read belongs in the answer.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/actions/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/actions/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAIrD,eAAO,MAAM,SAAS,EAAE,sBAAsB,CAAC,SAAS,CAEtD,CAAA"}
|
package/build/actions/config.js
CHANGED
|
@@ -1,34 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { advertisedConfig } from '@owlmeans/api-config';
|
|
2
2
|
import { handleRequest } from '@owlmeans/server-api';
|
|
3
|
-
import { PLUGINS } from '@owlmeans/config';
|
|
4
|
-
import { AppType, CONFIG_RECORD } from '@owlmeans/context';
|
|
5
3
|
export const advertise = handleRequest(async (_, ctx) => {
|
|
6
|
-
|
|
7
|
-
debug: ctx.cfg.debug ?? {},
|
|
8
|
-
brand: {},
|
|
9
|
-
services: Object.fromEntries(Object.entries(ctx.cfg.services ?? {}).map(([service, config]) => [
|
|
10
|
-
service, {
|
|
11
|
-
service: config.service,
|
|
12
|
-
type: config.type,
|
|
13
|
-
host: config.host,
|
|
14
|
-
port: config.port,
|
|
15
|
-
base: config.base
|
|
16
|
-
}
|
|
17
|
-
])),
|
|
18
|
-
plugins: (ctx.cfg[PLUGINS] ?? [])
|
|
19
|
-
.filter((plugin) => plugin.type === AppType.Frontend),
|
|
20
|
-
[CONFIG_RECORD]: (ctx.cfg[CONFIG_RECORD] ?? []).filter((record) => record.recordType != null && allowedConfigRecords.includes(record.recordType)),
|
|
21
|
-
...(Object.fromEntries(Object.entries(ctx.cfg).filter(([key]) => ![
|
|
22
|
-
'debug', 'services', PLUGINS, ...notAdvertizedConfigKeys
|
|
23
|
-
].includes(key)))),
|
|
24
|
-
...("oidc" in ctx.cfg ? {
|
|
25
|
-
oidc: {
|
|
26
|
-
clientCookie: ctx.cfg.oidc.clientCookie,
|
|
27
|
-
providers: ctx.cfg.oidc.providers?.map(provider => Object.fromEntries(Object.entries(provider)
|
|
28
|
-
.filter(([key]) => !['secret', 'apiClientId'].includes(key)))).filter(provider => provider.internal !== true),
|
|
29
|
-
}
|
|
30
|
-
} : {})
|
|
31
|
-
};
|
|
32
|
-
return apiConfig;
|
|
4
|
+
return advertisedConfig(ctx.cfg);
|
|
33
5
|
});
|
|
34
6
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/actions/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/actions/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAsC,aAAa,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;IACzF,OAAO,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAc,CAAA;AAC/C,CAAC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/api-config-server",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.18",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@owlmeans/api-config": "^0.1.18-rc.
|
|
25
|
-
"@owlmeans/server-api": "^0.1.18-rc.
|
|
26
|
-
"@owlmeans/server-context": "^0.1.18-rc.
|
|
27
|
-
"@owlmeans/server-entrypoint": "^0.1.18-rc.
|
|
24
|
+
"@owlmeans/api-config": "^0.1.18-rc.13",
|
|
25
|
+
"@owlmeans/server-api": "^0.1.18-rc.18",
|
|
26
|
+
"@owlmeans/server-context": "^0.1.18-rc.13",
|
|
27
|
+
"@owlmeans/server-entrypoint": "^0.1.18-rc.12"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@owlmeans/dep-config": "workspace:*",
|
package/src/actions/config.ts
CHANGED
|
@@ -1,50 +1,8 @@
|
|
|
1
1
|
import type { RefedEntrypointHandler } from '@owlmeans/server-entrypoint'
|
|
2
2
|
import type { ApiConfig } from '@owlmeans/api-config'
|
|
3
|
-
import
|
|
4
|
-
import type { PluginConfig } from '@owlmeans/config'
|
|
5
|
-
import { notAdvertizedConfigKeys, allowedConfigRecords } from '@owlmeans/api-config'
|
|
3
|
+
import { advertisedConfig } from '@owlmeans/api-config'
|
|
6
4
|
import { handleRequest } from '@owlmeans/server-api'
|
|
7
|
-
import { PLUGINS } from '@owlmeans/config'
|
|
8
|
-
import { AppType, CONFIG_RECORD } from '@owlmeans/context'
|
|
9
|
-
import type { ConfigRecord } from '@owlmeans/context'
|
|
10
5
|
|
|
11
6
|
export const advertise: RefedEntrypointHandler<ApiConfig> = handleRequest(async (_, ctx) => {
|
|
12
|
-
|
|
13
|
-
debug: ctx.cfg.debug ?? {},
|
|
14
|
-
brand: {},
|
|
15
|
-
services: Object.fromEntries(
|
|
16
|
-
Object.entries(ctx.cfg.services ?? {} as ServerConfig).map(([service, config]) => [
|
|
17
|
-
service, {
|
|
18
|
-
service: config.service,
|
|
19
|
-
type: config.type,
|
|
20
|
-
host: config.host,
|
|
21
|
-
port: config.port,
|
|
22
|
-
base: config.base
|
|
23
|
-
}
|
|
24
|
-
])
|
|
25
|
-
),
|
|
26
|
-
plugins: ((ctx.cfg as unknown as Record<string, PluginConfig[]>)[PLUGINS] ?? [])
|
|
27
|
-
.filter((plugin: PluginConfig) => plugin.type === AppType.Frontend),
|
|
28
|
-
[CONFIG_RECORD]: ((ctx.cfg as unknown as Record<string, ConfigRecord[]>)[CONFIG_RECORD] ?? []).filter(
|
|
29
|
-
(record: ConfigRecord) => record.recordType != null && allowedConfigRecords.includes(record.recordType)
|
|
30
|
-
),
|
|
31
|
-
...(
|
|
32
|
-
Object.fromEntries(
|
|
33
|
-
Object.entries(ctx.cfg).filter(([key]) => ![
|
|
34
|
-
'debug', 'services', PLUGINS, ...notAdvertizedConfigKeys
|
|
35
|
-
].includes(key))
|
|
36
|
-
)
|
|
37
|
-
),
|
|
38
|
-
...("oidc" in ctx.cfg ? {
|
|
39
|
-
oidc: {
|
|
40
|
-
clientCookie: (ctx.cfg.oidc as { clientCookie: unknown }).clientCookie,
|
|
41
|
-
providers: (ctx.cfg.oidc as { providers: Object[] }).providers?.map(
|
|
42
|
-
provider => Object.fromEntries(Object.entries(provider)
|
|
43
|
-
.filter(([key]) => !['secret', 'apiClientId'].includes(key)))
|
|
44
|
-
).filter(provider => provider.internal !== true),
|
|
45
|
-
}
|
|
46
|
-
} : {})
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return apiConfig
|
|
7
|
+
return advertisedConfig(ctx.cfg) as ApiConfig
|
|
50
8
|
})
|