@uniweb/build 0.21.0 → 0.23.0
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/package.json +8 -8
- package/src/site/index.js +4 -0
- package/src/site/plugin.js +14 -7
- package/src/uwx/site-project.js +22 -6
- package/src/uwx/site.js +19 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/build",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Build tooling for the Uniweb Component Web Platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -59,16 +59,16 @@
|
|
|
59
59
|
"js-yaml": "^4.1.0",
|
|
60
60
|
"sharp": "^0.35.3",
|
|
61
61
|
"yaml": "^2.5.0",
|
|
62
|
+
"@uniweb/projections": "^0.3.2",
|
|
63
|
+
"@uniweb/content-writer": "^0.3.3",
|
|
62
64
|
"@uniweb/schemas": "^0.2.10",
|
|
63
|
-
"@uniweb/
|
|
64
|
-
"@uniweb/theming": "^0.1.15",
|
|
65
|
-
"@uniweb/content-writer": "^0.3.3"
|
|
65
|
+
"@uniweb/theming": "^0.1.15"
|
|
66
66
|
},
|
|
67
67
|
"optionalDependencies": {
|
|
68
|
-
"@uniweb/schemas": "^0.2.10",
|
|
69
68
|
"@uniweb/content-reader": "^1.2.2",
|
|
70
|
-
"@uniweb/
|
|
71
|
-
"@uniweb/
|
|
69
|
+
"@uniweb/runtime": "^0.11.8",
|
|
70
|
+
"@uniweb/schemas": "^0.2.10",
|
|
71
|
+
"@uniweb/semantic-parser": "^1.2.2"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@tailwindcss/vite": "^4.0.0",
|
|
78
78
|
"@vitejs/plugin-react": "^4.0.0 || ^5.0.0",
|
|
79
79
|
"vite-plugin-svgr": "^4.0.0",
|
|
80
|
-
"@uniweb/core": "^0.
|
|
80
|
+
"@uniweb/core": "^0.9.0"
|
|
81
81
|
},
|
|
82
82
|
"peerDependenciesMeta": {
|
|
83
83
|
"vite": {
|
package/src/site/index.js
CHANGED
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
export { siteContentPlugin } from './plugin.js'
|
|
10
10
|
export { defineSiteConfig, readSiteConfig, default } from './config.js'
|
|
11
11
|
export { collectSiteContent } from './content-collector.js'
|
|
12
|
+
// The `agents:` vocabulary lives in @uniweb/projections (which owns the block);
|
|
13
|
+
// re-exported so the CLI can validate an author's spelling without taking a
|
|
14
|
+
// direct dependency on it. Same shape as the search re-exports.
|
|
15
|
+
export { AGENTS_KEYS } from '@uniweb/projections'
|
|
12
16
|
export { buildSiteData } from './build-site-data.js'
|
|
13
17
|
export { shouldSplitContent } from './split-content.js'
|
|
14
18
|
export {
|
package/src/site/plugin.js
CHANGED
|
@@ -513,13 +513,20 @@ export function siteContentPlugin(options = {}) {
|
|
|
513
513
|
/**
|
|
514
514
|
* Collect the site, then drop `knowledge:` pages.
|
|
515
515
|
*
|
|
516
|
-
* ⛔ **This is the bundle lane, and the bundle lane has no agent
|
|
516
|
+
* ⛔ **This is the bundle lane, and the bundle lane has no agent.**
|
|
517
517
|
* `uniweb export` and `uniweb deploy --host <adapter>` both run this pipeline
|
|
518
518
|
* (`cli/src/commands/export.js`, `deploy.js`), and their destinations are
|
|
519
|
-
* static hosts —
|
|
520
|
-
* `knowledge:` page is
|
|
521
|
-
*
|
|
522
|
-
*
|
|
519
|
+
* static hosts — files served as files, with no service running over the
|
|
520
|
+
* content. A `knowledge:` page is source material for such a service: prose
|
|
521
|
+
* written for it to reason with, addressed to it rather than to a person.
|
|
522
|
+
* Here there is no service to give it to, so publishing it would turn prose
|
|
523
|
+
* written for a machine reader into pages for visitors — the only readers
|
|
524
|
+
* this host has.
|
|
525
|
+
*
|
|
526
|
+
* ⚠️ **Not a confidentiality argument.** [Diego, 2026-08-13] *"It is not the
|
|
527
|
+
* case that it's private in the sense of sensitive."* The service quotes this
|
|
528
|
+
* material back to whoever prompts it, by design. The reason to drop it here
|
|
529
|
+
* is that it has no reader on this lane, not that it must be kept from one.
|
|
523
530
|
*
|
|
524
531
|
* Measured 2026-08-13, before this existed: a knowledge page became
|
|
525
532
|
* `dist/kb/index.html` — a public route — and its body rode in the
|
|
@@ -543,8 +550,8 @@ export function siteContentPlugin(options = {}) {
|
|
|
543
550
|
const routes = knowledgePages.map(page => page.route).join(', ')
|
|
544
551
|
console.warn(
|
|
545
552
|
`[site-content] Dropped ${knowledgePages.length} knowledge page(s) from this build: ${routes}\n` +
|
|
546
|
-
` This build targets a host that serves files only, so
|
|
547
|
-
`
|
|
553
|
+
` This build targets a host that serves files only, so nothing here reads them — their prose is ` +
|
|
554
|
+
`written for a site assistant, not for visitors. Use \`uniweb deploy\` to make them agent-readable.`
|
|
548
555
|
)
|
|
549
556
|
}
|
|
550
557
|
|
package/src/uwx/site-project.js
CHANGED
|
@@ -110,12 +110,27 @@ const INFO_TO_SITE_YML = {
|
|
|
110
110
|
// through `config.services` and resolved at render time, so it never enters
|
|
111
111
|
// `info` and a pull cannot launder it into authored config.
|
|
112
112
|
//
|
|
113
|
-
// ⚠️
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
113
|
+
// ⚠️ Credential-shaped keys are STRIPPED ON PUSH (`stripCredentials`), so the
|
|
114
|
+
// backend never stores one and it cannot come back. What that does to the
|
|
115
|
+
// author's file depends on which direction they are pulling into, and the two
|
|
116
|
+
// differ — ⛔ this comment asserted the wrong one until it was run:
|
|
117
|
+
//
|
|
118
|
+
// - `pull` over an EXISTING site.yml — the local `apiKey` SURVIVES.
|
|
119
|
+
// `mergeYamlConfig` spreads one level (`{...existing[key], ...value}`), so
|
|
120
|
+
// the projected `{endpoint, …}` merges over the local block and nothing
|
|
121
|
+
// removes a key the document does not carry.
|
|
122
|
+
// - `clone` into a fresh directory — no local block exists, so the file is
|
|
123
|
+
// written from the document alone and has no `apiKey`.
|
|
124
|
+
//
|
|
125
|
+
// Both are correct: a pull does not silently delete something the author
|
|
126
|
+
// typed, and the push already warned them. The security property is upheld at
|
|
127
|
+
// the push, not by the pull. Measured end-to-end against a live uniwebd —
|
|
128
|
+
// every unit test passed before and after, so only a real push touched it.
|
|
118
129
|
assistant: 'assistant',
|
|
130
|
+
// Authored-only, like `submit` and `assistant`: a host's tracking endpoint is
|
|
131
|
+
// offered through `config.services.tracking` and resolved at render, so it
|
|
132
|
+
// never enters `info` and a pull cannot launder it into authored config.
|
|
133
|
+
tracking: 'tracking',
|
|
119
134
|
paths: 'paths',
|
|
120
135
|
data: 'data',
|
|
121
136
|
template: 'template',
|
|
@@ -358,7 +373,7 @@ export function pageSectionsToFiles({ pageDir, pageSections, ctx, pageContext })
|
|
|
358
373
|
// and preserved. Keep in sync with pageRecordToYml below.
|
|
359
374
|
const PAGE_YML_MANAGED_KEYS = new Set([
|
|
360
375
|
'id', 'title', 'description', 'label', 'keywords', 'index', 'hidden',
|
|
361
|
-
'hideIn', 'redirect', 'rewrite', 'layout', 'seo',
|
|
376
|
+
'hideIn', 'knowledge', 'redirect', 'rewrite', 'layout', 'seo',
|
|
362
377
|
'fetch', 'sections',
|
|
363
378
|
])
|
|
364
379
|
|
|
@@ -380,6 +395,7 @@ function pageRecordToYml(record, sectionsArray, sourceLocale) {
|
|
|
380
395
|
if (record.is_index) y.index = true
|
|
381
396
|
if (record.hidden !== undefined) y.hidden = record.hidden
|
|
382
397
|
if (record.hide_in !== undefined) y.hideIn = record.hide_in
|
|
398
|
+
if (record.knowledge !== undefined) y.knowledge = record.knowledge
|
|
383
399
|
if (record.redirect !== undefined) y.redirect = record.redirect
|
|
384
400
|
if (record.rewrite !== undefined) y.rewrite = record.rewrite
|
|
385
401
|
if (record.layout !== undefined) y.layout = record.layout
|
package/src/uwx/site.js
CHANGED
|
@@ -201,6 +201,11 @@ function buildPageData(config, ctx) {
|
|
|
201
201
|
setIf(data, 'hidden', config.hidden)
|
|
202
202
|
const hideIn = normalizeHideIn(config)
|
|
203
203
|
if (hideIn.length) data.hide_in = hideIn
|
|
204
|
+
// Agent-only content. Sent as authored — only the marked page carries it, and
|
|
205
|
+
// the cascade to descendants is the CONSUMER's to compute (by route prefix, or
|
|
206
|
+
// equivalently by walking the page tree). A reader that tests this field alone
|
|
207
|
+
// honours the branch root and silently misses every child.
|
|
208
|
+
setIf(data, 'knowledge', config.knowledge)
|
|
204
209
|
setIf(data, 'redirect', config.redirect)
|
|
205
210
|
setIf(data, 'rewrite', config.rewrite)
|
|
206
211
|
setIf(data, 'layout', config.layout)
|
|
@@ -756,6 +761,20 @@ export async function siteProjectToDocument(siteRoot, opts = {}) {
|
|
|
756
761
|
//
|
|
757
762
|
// ⛔ Credentials are stripped, not trusted — see `stripCredentials`.
|
|
758
763
|
setIf(info, 'assistant', stripCredentials(siteYml.assistant, 'assistant'))
|
|
764
|
+
// `tracking` — where this site's usage events go (`endpoint`, read by the
|
|
765
|
+
// runtime through `resolveService`, plus `consent:`). Same family as
|
|
766
|
+
// `search`/`submit`/`assistant` and here for the same reason: the bundle lane
|
|
767
|
+
// spreads all of site.yml while this one is an allowlist, so without this line
|
|
768
|
+
// an authored `tracking:` works on a static host and vanishes silently on the
|
|
769
|
+
// synced lane.
|
|
770
|
+
//
|
|
771
|
+
// ⛔ Credentials stripped like `assistant`. A collector that wants a write key
|
|
772
|
+
// is a real shape, and this block is published world-readable — but note the
|
|
773
|
+
// strip only reaches a KEYED FIELD: a key embedded in the endpoint URL itself
|
|
774
|
+
// (`https://collector/e?key=…`) is invisible here and is disclosed. The host's
|
|
775
|
+
// secret store is the only right home either way.
|
|
776
|
+
// (kb/framework/plans/tracking.md)
|
|
777
|
+
setIf(info, 'tracking', stripCredentials(siteYml.tracking, 'tracking'))
|
|
759
778
|
setIf(info, 'paths', siteYml.paths)
|
|
760
779
|
setIf(info, 'data', siteYml.data ?? siteYml.fetch)
|
|
761
780
|
// `app` — the deployment's `@uniweb/app-spec` reference (a bare uuid string),
|