Skip to content

feat: OssieSynonymIndex + strict-version-check - #4

Merged
buggtb merged 1 commit into
mainfrom
feature/synonym-index-and-version-check
Jul 9, 2026
Merged

feat: OssieSynonymIndex + strict-version-check#4
buggtb merged 1 commit into
mainfrom
feature/synonym-index-and-version-check

Conversation

@buggtb

@buggtb buggtb commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Closes ossie#2 (strict version check) and ossie#3 (synonym index).

OssieSynonymIndex

Three static builders (buildFieldIndex, buildMetricIndex,
buildDatasetIndex) that walk an SemanticModel and return a
lowercased-synonym → canonical-name map. Plus a resolve() helper
that either rewrites a caller-supplied name to its canonical form,
or returns the input unchanged if it isn't a synonym.

First-declared-wins on synonym collisions (pragmatic default —
consumers wanting strict ambiguity detection can walk the model
themselves).

10 unit tests cover: metric / field / dataset synonyms, case
insensitivity, null / empty model handling, collision precedence,
resolve-doesn't-rewrite-canonical.

Strict version check

OssieYamlReader.setStrictVersion(true) opts in to rejecting
documents whose version field isn't in SUPPORTED_VERSIONS
(currently {0.1.0, 0.1.1, 0.2.0.dev0}). Permissive mode
(default) accepts anything, matching the pre-existing behaviour.

New typed exception: UnsupportedOssieVersionException carrying
the observed version + the supported set, with a helpful message.

6 unit tests cover: permissive accepts unknown, strict accepts every
known version, strict rejects unknown, missing-version handling,
fluent setter.

README

New sections showing OssieSynonymIndex.resolve() and
setStrictVersion(true) usage. Compatibility section now names the
SUPPORTED_VERSIONS constant.

Closes #2, #3.

- OssieSynonymIndex: three builders (field / metric / dataset) that
  produce a lowercased-synonym → canonical-name map, plus a resolve()
  helper. First-declared-wins on collisions. 10 tests cover case
  insensitivity, null model handling, collision precedence.
- OssieYamlReader.setStrictVersion(true): opt-in rejection of unknown
  versions. New SUPPORTED_VERSIONS constant lists {0.1.0, 0.1.1,
  0.2.0.dev0} — covers dbt 1.12's output (0.1.1) + apache/ossie head
  (0.2.0.dev0). New UnsupportedOssieVersionException carries the
  observed version + supported set with a diagnostic message. 6 tests
  cover permissive / strict / missing-version / fluent setter.
- README: new sections showing both features + updated compatibility
  section.
@buggtb
buggtb merged commit 25b979e into main Jul 9, 2026
2 checks passed
pull Bot pushed a commit to AKJUS/saiku that referenced this pull request Jul 9, 2026
…piculedata#1408, spiculedata#1409)

Wires the OSI ai_context.synonyms and custom_extensions[] blocks
through the DTO layer, the AI schema view, and the query validator so
agents can refer to entities by synonym and consumer-side tooling can
carry vendor annotations without dropping them.

## saiku#1408 — synonyms

- OssieModelDto gains fieldAliases / metricAliases / datasetAliases
  maps. OssieDiscoverService populates them via the library's
  bi.saiku.ossie.OssieSynonymIndex — dogfooding the ossie-core helper
  we shipped in spiculedata/ossie#4.
- OssieAiSchemaProjector copies the alias maps to the AI schema view
  so they surface on GET /ai/ossie/schema.
- OssieAiValidator resolves synonyms before rejecting names on
  POST /ai/ossie/query:
  - Dataset synonyms rewrite ref.dataset in place; downstream code sees
    the canonical name only.
  - Metric synonyms rewrite ref.metric similarly.
  - Field synonyms only rewrite when the alias resolves to a field on
    the SAME dataset the caller asked for — cross-dataset synonyms
    (ambiguous by design) get rejected instead of silently misrouting.

## saiku#1409 — custom_extensions

- New CustomExtensionDto in org.saiku.service.ossie — thin wire model
  carrying vendor_name + parsed JSON data.
- OssieModelDto.Field / Dataset / Metric gain customExtensions lists;
  discover service parses each extension's opaque data string into a
  JsonNode once so consumers walk it structurally.
- 'visibility: internal' filter: any extension whose parsed data
  declares visibility=internal is dropped at the discover-service
  boundary. That's the standard escape hatch for tooling-private
  metadata (Saiku's own annotations, dbt's tool-only bookkeeping)
  that shouldn't reach an agent-facing view.
- OssieAiSchema.Field / Dataset / Metric gain customExtensions
  passthrough; projector copies straight across.

## Verification

- Full reactor tests: BUILD SUCCESS
- saiku-service: 769/769 (was 760; +9 new tests)
  - OssieAiValidatorTest: +4 synonym-resolution cases (metric alias
    rewrite, dataset alias rewrite, field alias rewrite when dataset
    matches, field alias IGNORED when cross-dataset)
  - OssieAiSchemaProjectorTest: +3 (alias maps carry through, custom
    extensions carry through on field, on dataset + metric)
  - OssieDiscoverServiceTest: +2 (synonym aliases populated from
    ai_context, visibility:internal extensions filtered)
- saiku-sql: SaikuOssieConnectionTest still 2/2
- Zero behavioural regressions on existing tests

## Docs

docs/AI-OSSIE-API.md gains two new subsections under Step 2:
- "AI-context synonyms (spiculedata#1408)" — shows fieldAliases/metricAliases/
  datasetAliases shape + describes the request-rewriting behaviour +
  documents the cross-dataset ambiguity guard
- "Custom extensions passthrough (spiculedata#1409)" — shows the customExtensions
  shape + the visibility:internal filter with a YAML example
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant