Two reports from the 08-24 feedback sweep (seq 261545):
- The bulk-book queue title (Samlingsverifikation: 1 transaktioner
2026-07-22) carried no amount, direction or counterparty; the CEO
approving from a phone could not tell what he authorised. Titles now
read: Samlingsverifikation -1 000,00 SEK 2026-05-12: NORDNET UTTAG
(+1 till). Same per-tx text the categorize titles already carry;
preview_data stays aggregate-only.
- gnubok_query_journal called with {query} instead of {text} silently
returned the whole journal. tools/call now rejects unknown top-level
parameters for every tool (all schemas declare additionalProperties:
false) with a VALIDATION_ERROR that lists the valid keys. company_id
stays tolerated everywhere. codedError is exported from
company-routing for the dispatcher.
The copy fixes this branch originally carried (scope-honest
list_pending_operations, BFL 5 kap 6 § on create_voucher, bank-movement
only on categorize/bulk_book) landed independently in #1844 and were
dropped on rebase; no catalog token change remains.
Claude-Session: https://claude.ai/code/session_01ScVhg6XsDtNXkiEQNV7LaZ
Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
46 lines
1.7 KiB
TypeScript
46 lines
1.7 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { findUnknownArgKeys, listArgKeys } from '../arg-guard'
|
|
import { tools } from '../server'
|
|
|
|
describe('findUnknownArgKeys', () => {
|
|
const schema = {
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
properties: { text: { type: 'string' }, limit: { type: 'number' } },
|
|
}
|
|
|
|
it('flags keys the schema does not declare', () => {
|
|
expect(findUnknownArgKeys(schema, { query: 'moms', limit: 5 })).toEqual(['query'])
|
|
})
|
|
|
|
it('returns nothing for a well-formed call', () => {
|
|
expect(findUnknownArgKeys(schema, { text: 'moms' })).toEqual([])
|
|
expect(findUnknownArgKeys(schema, {})).toEqual([])
|
|
})
|
|
|
|
it('tolerates company_id everywhere (the routing layer owns it)', () => {
|
|
expect(findUnknownArgKeys(schema, { text: 'x', company_id: 'c-1' })).toEqual([])
|
|
})
|
|
|
|
it('is inert for a schema that allows additional properties', () => {
|
|
expect(findUnknownArgKeys({ type: 'object', additionalProperties: true }, { anything: 1 })).toEqual([])
|
|
})
|
|
|
|
it('lists the declared keys for the error message', () => {
|
|
expect(listArgKeys(schema)).toEqual(['text', 'limit'])
|
|
expect(listArgKeys({ type: 'object' })).toEqual([])
|
|
})
|
|
|
|
it('would have caught the reported gnubok_query_journal misspelling', () => {
|
|
// Feedback seq 261545: {query: "..."} instead of {text: "..."} returned the
|
|
// whole journal (7321 rows) with applied_filters.text null.
|
|
const queryJournal = tools.find((t) => t.name === 'gnubok_query_journal')!
|
|
const unknown = findUnknownArgKeys(
|
|
queryJournal.inputSchema as Record<string, unknown>,
|
|
{ query: 'hyra' },
|
|
)
|
|
expect(unknown).toEqual(['query'])
|
|
expect(listArgKeys(queryJournal.inputSchema as Record<string, unknown>)).toContain('text')
|
|
})
|
|
})
|