@panaversity/ksor 0.0.9 → 0.0.10
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/CHANGELOG.md +155 -0
- package/dist/cli.mjs +452 -66
- package/package.json +1 -1
- package/templates/scaffold/AGENTS.md +18 -17
- package/templates/scaffold/README.md +1 -1
- package/templates/scaffold/env.example +6 -5
- package/templates/scaffold/instance.md +4 -1
- package/templates/scaffold/system/site/lib/order-rule.ts +107 -0
- package/templates/scaffold/system/site/lib/page-order.ts +93 -0
- package/templates/scaffold/system/site/lib/source.ts +9 -48
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,160 @@
|
|
|
1
1
|
# @panaversity/ksor
|
|
2
2
|
|
|
3
|
+
## 0.0.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c07a5db: `ksor calibrate` states what its measurement is worth, not just its result
|
|
8
|
+
|
|
9
|
+
The default door synthesizes in-corpus questions by asking a model to write one
|
|
10
|
+
FROM each sampled passage, then scores those questions against the corpus that
|
|
11
|
+
contains the passage. They share vocabulary a reader's question will not, so the
|
|
12
|
+
in-corpus distribution sits higher than real traffic will and the separation the
|
|
13
|
+
run reports is an UPPER BOUND. The `--queries-file` door carried a caveat about
|
|
14
|
+
its own distribution; the default door — the biased one — carried none.
|
|
15
|
+
|
|
16
|
+
Found live: a real record calibrated this way reported min in-corpus 0.682
|
|
17
|
+
against max out-of-corpus 0.580 and recommended `vector_floor: 0.631`. Questions
|
|
18
|
+
the record demonstrably answers then scored 0.530 to 0.606 — every one below the
|
|
19
|
+
recommended floor. Pasting it would have made the record abstain on questions
|
|
20
|
+
whose answers it had just cited, which is the failure abstention exists to
|
|
21
|
+
prevent, arrived at from the other side.
|
|
22
|
+
|
|
23
|
+
The block now carries that caveat, and prints the one number it always left the
|
|
24
|
+
reader to work out: the separation margin, with the probe counts behind it. A
|
|
25
|
+
margin of 0.054 over six in-corpus and four out-of-corpus probes is a different
|
|
26
|
+
claim from the same margin over sixty, and both figures were already on the
|
|
27
|
+
report without ever reaching the page. The mathematics and the recommended value
|
|
28
|
+
are unchanged.
|
|
29
|
+
|
|
30
|
+
It also names the generation it measured. With nothing pinned — the ordinary
|
|
31
|
+
case, calibrating what is being served — the report carried no generation at
|
|
32
|
+
all, so the provenance comment beside a pasted floor read `on generation unknown
|
|
33
|
+
(no generation pinned)`. A floor is a threshold inside ONE generation's embedding
|
|
34
|
+
space, and the query that counts the chunks had already resolved which one.
|
|
35
|
+
|
|
36
|
+
`runCalibration` had no test of any kind; it has one now, against real Postgres.
|
|
37
|
+
|
|
38
|
+
- d00f3a2: The signing keys are discovered, not guessed — any standards-compliant SSO now works.
|
|
39
|
+
|
|
40
|
+
`KSOR_SSO_URL` is documented as "the AS base", and the verifier appended one
|
|
41
|
+
vendor's layout to it (`/api/auth/jwks`, Better Auth's). Auth0, Okta, Entra,
|
|
42
|
+
Keycloak, Cognito and Google all publish elsewhere, so every one of them failed
|
|
43
|
+
the key fetch — which is classified transient, so the door booted clean and
|
|
44
|
+
returned 503 to every request with nothing naming the cause. The only posture an
|
|
45
|
+
operator could actually reach was `KSOR_ALLOW_PUBLIC_UNAUTHENTICATED=1`: the one
|
|
46
|
+
key we handed people was the one that props the door open.
|
|
47
|
+
|
|
48
|
+
`jwks_uri` is now read from the SSO's own metadata document — RFC 8414 first,
|
|
49
|
+
then OpenID Discovery — with `KSOR_JWKS_URL` kept as an explicit override, and
|
|
50
|
+
the vendor path kept as a last resort that reports itself as a guess. Where the
|
|
51
|
+
keys came from is stated on the boot line.
|
|
52
|
+
|
|
53
|
+
Verified against three real providers: Google (RFC 8414, cross-origin
|
|
54
|
+
`jwks_uri`), GitHub Actions OIDC, and Entra — whose issuer carries a path,
|
|
55
|
+
the case a naive `${sso}/.well-known/…` gets wrong.
|
|
56
|
+
|
|
57
|
+
Discovery never refuses to boot: an unreachable AS falls back and says so.
|
|
58
|
+
|
|
59
|
+
- 9062088: A loopback authorization server's keys are reachable again.
|
|
60
|
+
|
|
61
|
+
JWKS discovery refused a cleartext `jwks_uri`, which is right for a network AS
|
|
62
|
+
and wrong for a local one: a dev authorization server on loopback advertises
|
|
63
|
+
`http://127.0.0.1:…/jwks`, the resolver refused it, the vendor guess was used
|
|
64
|
+
instead, and every request returned 503. `assertHttpUrl` already exempts
|
|
65
|
+
loopback for the SSO base for exactly this reason; the resolver now does too.
|
|
66
|
+
Cleartext to any non-loopback host is still refused.
|
|
67
|
+
|
|
68
|
+
Found by writing the first test that boots the gateway in bearer mode.
|
|
69
|
+
|
|
70
|
+
- 995ec48: A governance act names its actor; the tool no longer guesses one.
|
|
71
|
+
|
|
72
|
+
`ksor takedown --actor` fell back to `$USER` / `$USERNAME` / `"operator"`, so a
|
|
73
|
+
ledger row read `runner` under CI and `root` in a container — a self-asserted
|
|
74
|
+
string wearing a schema, indistinguishable from a person who was never there.
|
|
75
|
+
`retrieval_log.actor` is `NOT NULL` with the comment "NO default: unset errors
|
|
76
|
+
loudly", and the fallback is precisely what stopped it erroring.
|
|
77
|
+
|
|
78
|
+
Denying or revoking now REFUSES without `--actor`, before the DSN is resolved:
|
|
79
|
+
a missing actor is an argument error (exit 1), not an environment one. The
|
|
80
|
+
read-only modes — `--list`, `--ledger`, `--export` — write no ledger row and
|
|
81
|
+
need nothing.
|
|
82
|
+
|
|
83
|
+
- 41b0c38: Reading order is one rule again: the MCP door now reads `order:`
|
|
84
|
+
|
|
85
|
+
`order:` is the only ordering key a record may declare — it is in the governed
|
|
86
|
+
frontmatter set the format checker closes, and the checker's own remedy for a
|
|
87
|
+
stray `meta.json` says so. The MCP door never read it. The tree adapter was
|
|
88
|
+
converted from the predecessor, whose ordering keys were Docusaurus's
|
|
89
|
+
`position:` / `sidebar_position:`, neither of which a compliant record may
|
|
90
|
+
declare — so `outline` reported the record's structure in filename order and
|
|
91
|
+
called it the reading order, while the website honoured `order:`. On a
|
|
92
|
+
curriculum, where reading order IS the content, an agent asking "what do I read
|
|
93
|
+
first" got a different answer from the two surfaces.
|
|
94
|
+
|
|
95
|
+
Four smaller disagreements went with it, each now a row in a shared decision
|
|
96
|
+
table: unordered documents sorted at 10 000 rather than after everything;
|
|
97
|
+
fractional orders were truncated; ties compared `example.md` against
|
|
98
|
+
`example-two.md`, where `.` sorts after `-`, reversing ordinary pairs; and one
|
|
99
|
+
side folded case while the other did not.
|
|
100
|
+
|
|
101
|
+
The rule now lives in one file, copied into the scaffold and asserted
|
|
102
|
+
byte-identical, with `ORDER_CASES` run against BOTH surfaces — so a surface that
|
|
103
|
+
drifts fails on the row it broke.
|
|
104
|
+
|
|
105
|
+
- 41b0c38: `ksor serve` reports its own posture instead of forwarding other people's warnings
|
|
106
|
+
|
|
107
|
+
Booting printed four alarming paragraphs at an operator who had done nothing
|
|
108
|
+
wrong: the driver's multi-line `SECURITY WARNING` about `sslmode` aliases, ksor's
|
|
109
|
+
own three-line restatement of the same thing, and the MCP SDK's note about a
|
|
110
|
+
`responseMode` ksor chose deliberately.
|
|
111
|
+
|
|
112
|
+
The driver's warning is correct and its remedy is one word, so ksor now applies
|
|
113
|
+
it: a remote `sslmode=require|prefer|verify-ca` is rewritten to `verify-full`
|
|
114
|
+
before the connection is made. The connection is unchanged today — pg 8 was
|
|
115
|
+
already resolving all three to full verification, which is the entire content of
|
|
116
|
+
its warning — and it can no longer be silently downgraded by a driver upgrade.
|
|
117
|
+
The SDK's note describes a recorded decision, not a defect, and is suppressed by
|
|
118
|
+
exact message so that anything else it says still reaches the operator.
|
|
119
|
+
|
|
120
|
+
What is left is the record's posture, aligned and in ksor's own voice, with the
|
|
121
|
+
two lines that decide whether to trust what happens next saying what they mean:
|
|
122
|
+
auth `DISABLED` now names the bind it is survivable on, and an absent abstention
|
|
123
|
+
floor says out-of-corpus questions will be answered rather than refused.
|
|
124
|
+
|
|
125
|
+
- bea7d80: `read` names every section it will accept, not just the top-level ones
|
|
126
|
+
|
|
127
|
+
`read` resolves a `heading` three ways: a full heading path, any prefix of one,
|
|
128
|
+
and a section's last segment when that segment is unique in the document. The
|
|
129
|
+
error for a section it could not find listed only the TOP-LEVEL segments — a
|
|
130
|
+
strict subset of its own vocabulary — so it reported real, reachable sections as
|
|
131
|
+
absent. Found live: a nested section was refused by name and served on the next
|
|
132
|
+
call under the same name.
|
|
133
|
+
|
|
134
|
+
The error now lists the full heading paths (the form that always resolves and
|
|
135
|
+
never collides), states the unique-last-segment shorthand rather than doubling
|
|
136
|
+
the list to enumerate it, and counts the tail past twenty instead of printing an
|
|
137
|
+
unbounded list. The `heading` input and the `sections` output now describe the
|
|
138
|
+
same vocabulary in the tool schema, where an agent reads it before making the
|
|
139
|
+
call rather than after failing one.
|
|
140
|
+
|
|
141
|
+
- 4631268: Correct every remaining document that said `pnpm serve` publishes.
|
|
142
|
+
|
|
143
|
+
`serve` was `pnpm schema && pnpm grant && pnpm ingest && ksor serve` and is now
|
|
144
|
+
`ksor serve` alone. Three adopter-facing places still described the old chain:
|
|
145
|
+
the scaffolded `instance.md`'s own comment ("copy .env.example to .env, then run
|
|
146
|
+
`pnpm serve`"), the scaffold README's file table ("the agent surface: schema →
|
|
147
|
+
grant → ingest → serve"), and AGENTS.md's runbook ("`pnpm serve` is the only
|
|
148
|
+
command this rung needs"). Following any of them serves an empty record.
|
|
149
|
+
|
|
150
|
+
All three now say the same thing the CLI does: `pnpm provision` once,
|
|
151
|
+
`pnpm refresh` to publish, `pnpm serve` to serve — and why publishing is
|
|
152
|
+
separate, since a restart or an autoscaling event must not republish a record.
|
|
153
|
+
|
|
154
|
+
A test now asserts the CLAIM rather than the command. The existing guard could
|
|
155
|
+
not catch this: it checks that a named command exists, and `pnpm serve` does
|
|
156
|
+
exist — what was wrong was the sentence attached to it.
|
|
157
|
+
|
|
3
158
|
## 0.0.9
|
|
4
159
|
|
|
5
160
|
### Patch Changes
|