Skip to content

[FSTORE-2096] Attachment timestamps, the keyword API, and tags for jobs, apps and deployments - #635

Merged
jimdowling merged 5 commits into
logicalclocks:mainfrom
jimdowling:FSTORE-2096-timestamps-keywords-job-tags
Aug 21, 2026
Merged

[FSTORE-2096] Attachment timestamps, the keyword API, and tags for jobs, apps and deployments#635
jimdowling merged 5 commits into
logicalclocks:mainfrom
jimdowling:FSTORE-2096-timestamps-keywords-job-tags

Conversation

@jimdowling

@jimdowling jimdowling commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Documentation for FSTORE-2096. Sibling PRs: logicalclocks/hopsworks-ee#3227, logicalclocks/hopsworks-api#1104, logicalclocks/hopsworks-front#2042, logicalclocks/hopsworks-helm#2212, logicalclocks/loadtest#984.

What this adds

Page Status Covers
user_guides/fs/tags/tags.md edited Jobs and apps as taggable artifacts, the archive flag on a schema, and a new section on attachment times.
user_guides/fs/tags/keywords.md new The keyword API: read, add, replace, delete, attachment times, the cluster vocabulary, and the CLI.
user_guides/projects/search.md new The ten search classes, filtering by tag key and value, the REST call, api-key scopes, and the tag facets endpoint.
setup_installation/admin/search_index.md new The Search Index admin page, stuck commands and cancelling them, reindexing, and the three cluster variables.
concepts/projects/search.md edited What is searchable, why apps and agents are narrowings, and the cross-project switch.

Two corrections, not just additions

Both of these were accurate before this ticket and are wrong after it, so they are fixed rather than extended.

tags.md said tags on models and deployments "are not indexed for free text search". They are now index documents, so the sentence claimed the opposite of the shipped behaviour.

concepts/projects/search.md listed four searchable asset types where there are now seven. It also did not say that keywords are limited to feature groups, feature views and training data while tags are not. That asymmetry is the thing a reader needs, because it decides whether a keyword filter can answer their question at all: a keyword filter can never match a job, a model or a deployment.

Choices worth flagging for review

The archive flag is documented as recording intent with no behaviour yet. It is settable and persisted, and nothing reads it; copying deleted attachments into an offline feature group is a later change. Documenting it silently as though it archives today would be wrong, and omitting it leaves an unexplained checkbox in the UI. The note also says why setting it early matters: it cannot recover attachments deleted while it was off.

The CLI change is a warning, not a note. The *-keyword commands previously operated on tags. A script passing --value to add-keyword has to move to add-tag, and a keyword has no value argument to pass, so this breaks such a script rather than merely changing output.

The search guide states the app/agent partition explicitly. An app is a job and an agent is a deployment, each excluded from the class it narrows. This is documented because it is the part that fails quietly: a wrong discriminator still returns documents and plausible counts, just the wrong ones.

Verification

Every command in the repo's CI was run locally against this branch:

  • mkdocs build -s (strict): passes, no new warnings. The only INFO lines are pre-existing (three unnav'd Databricks pages and an airflow3.md anchor).
  • markdownlint-cli2 "docs/**/*.md": 0 issues across 235 files.
  • hopsworks-docs snakeoil: passes, and git diff --exit-code is clean on the committed tree, which is the check CI actually enforces.

The API docs section was built against this ticket's client (hopsworks-api on FSTORE-2096-timestamps-keywords-job-tags) rather than main, so the generated reference matches the surface described here.

Every documented symbol was executed, not read off the diff. All 23 SDK methods were resolved and their signatures compared against the prose; hops fg/fv/td/job --help was run to confirm each documented subcommand exists. This caught one real error: the tag schema example was originally written against a project.get_tag_schemas_api() accessor that does not exist, and is now TagSchemasApi() with its verified import path and archive: bool = False signature.

Facts taken from the backend rather than assumed: the missing-filter rejection is 422 (GenericErrorCode.ILLEGAL_ARGUMENT maps to UNPROCESSABLE_ENTITY, not 400), the scope mapping is read from OpenSearchApiKeyScopes, the response bucket names from OpenSearchFeaturestoreDTO, and the retry defaults from Settings.

Not covered

Overlap with #629

#629 (FSTORE-2075) was written while these two tickets were one, so it also touches tags.md, keywords.md and concepts/projects/search.md. This PR carries only the FSTORE-2096 half and branches from main, not from #629.

Expect a conflict in those three files whichever lands second; the resolution is keep-both, since the two describe different features. The merge order on the ticket is this one first, then FSTORE-2075.

…bs, apps and deployments

https://hopsworks.atlassian.net/browse/FSTORE-2096

Documents the user-facing and operator-facing surface this ticket adds:
attachment timestamps on tags and keywords, the keyword API and its CLI,
tags on jobs and apps, the archive flag on a tag schema, the four new
search classes, and the administration of the search index behind them.

Two existing statements were wrong once this shipped, rather than merely
incomplete, so they are corrected here. The tags guide said tags on
models and deployments are not indexed for free-text search; those are
now index documents. The search concept page listed four searchable
asset types; there are now seven, and it did not say that keywords are
limited to feature groups, feature views and training data while tags
are not, which is the distinction that decides which of the two a filter
can use.

The keywords page carries the CLI break in a warning rather than a note.
The *-keyword commands previously operated on tags, so a script passing a
value to add-keyword needs add-tag instead, and a keyword has no value
argument to pass.

The search guide states the partition that makes apps and agents work,
because it is the part that fails silently: an app is a job and an agent
is a deployment, each excluded from the class it narrows, so a wrong
discriminator returns plausible results rather than an error. It also
records that a request with no filter is refused with 422, that a
docType outside an api key's scopes is refused while ALL is narrowed
instead, and that the tag facets read is bounded and reports partial
when it did not see everything.

The admin page explains why a single stuck index command matters more
than one failure suggests: commands for one document apply in order, so
later updates to that document wait behind it while other documents are
unaffected. Cancelling is described as losing that update, since the
index keeps what it already held.

Every documented method, CLI command and import path was executed
against the branch's client rather than read from the diff, which is what
caught the tag schema example: it was written against a project accessor
that does not exist.

Reviewed-by: Claude Opus 5 (1M context)
Signed-off-by: Jim Dowling <jim@logicalclocks.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jimdowling and others added 2 commits August 20, 2026 08:08
…bs, apps and deployments

https://hopsworks.atlassian.net/browse/FSTORE-2096

Say what the tag archive flag is for. The section described the mechanism,
keeping attachments that would otherwise be discarded, without saying why
anyone would want that, which left the checkbox looking like retention
for its own sake.

The reason is analytics on a tag's history rather than its current value.
The worked example is an asset_lifecycle tag whose state moves dev to qa
to prod: read live it says only where an artifact is now, while the
questions worth asking are about the pipeline, such as how long something
sits in qa before it reaches prod and whether that is getting slower.
Those need one record per value with the time that value became current,
which is what archiving retains, and the analysis is then a group-by over
the artifact taking the gaps between its records.

Also separates that history from the live attachment time, because the
two are easy to conflate and this page documents both. The live timestamp
stays at the first attachment when a value is corrected, so it records
when an artifact was first classified, not when it entered its current
state, and it therefore cannot answer the transition question on its own.

Reviewed-by: Claude Opus 5 (1M context)
Signed-off-by: Jim Dowling <jim@logicalclocks.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jimdowling
jimdowling requested review from o-alex and rcnnnghm August 20, 2026 20:17
…bs, apps and deployments

https://hopsworks.atlassian.net/browse/FSTORE-2096

Document the stuck marker the Search Index page now shows at 20
attempts, and why the threshold sits there: the retry delay has been at
its cap for a while by then, so crossing it means roughly an hour of the
same failure. The remedial order matters and is stated: read the error
first, since a failure whose cause was already fixed clears itself on
the next retry, and only otherwise cancel.

Reviewed-by: Claude Opus 5 (1M context)
Signed-off-by: Jim Dowling <jim@logicalclocks.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…bs, apps and deployments

https://hopsworks.atlassian.net/browse/FSTORE-2096

The stuck-command list moved in the admin UI: it is now the OpenSearch
Index Commands tab under Service Operations rather than its own menu
entry. Update the navigation instruction, and document the two attention
cues that replace the menu presence it lost: the pulsing orange dot on
the Service Operations menu item and the orange outline on the tab,
both of which appear and clear on their own as the queue fails and
drains. Stated so an operator knows the absence of the dot is
information too: no dot means there is nothing to look at.

Reviewed-by: Claude Opus 5 (1M context)
Signed-off-by: Jim Dowling <jim@logicalclocks.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jimdowling
jimdowling merged commit 1978558 into logicalclocks:main Aug 21, 2026
1 check passed
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.

2 participants