Change log#
0.23.0 (2026-07-09)#
Backwards-incompatible changes#
POST /ingest/resources/documentsnow returns a list of per-item ingest results instead of a bare list of document resources. Each result reports the document’shandle, astatusofcreated,updated, orfailed, the storedresource(on success), and anerrordetail (on failure). Error details are sanitized to the exception class and first message line, so SQL statements and bound parameters no longer appear in responses.Every existing
resourceID is re-minted as a time-ordered ID indate_createdorder by a one-time Alembic data migration, which rewrites the dependent foreign keys indocument_resource,contributor, andresource_relationin the same transaction. This is a deliberate one-time ID break: resource IDs and URLs issued by earlier releases are invalid after the upgrade. This release requires Alembic migrationscf936213314d,3b66bd60b53f, and20144e072aa7.Contributor listings in resource responses no longer include the author’s
emailaddress, which is personal data. The affiliationemail_domainfield (a non-personal organizational domain) is unchanged.
New features#
Added an external link-checking service with a submit-and-poll API.
POST /ook/linkcheck/checksaccepts a website build’s external URLs (anorigin_base_urlidentifying the website, anis_default_versionflag, and a list of URLs with the origin-relative page paths they occur on). Any public website is supported: the origin base URL is a full http(s) URL (path-bearing bases likehttps://rsp.lsst.io/guidesare allowed) and is normalized by lowercasing the host and stripping any trailing slash. URLs are canonicalized (fragments stripped) and partitioned: URLs with a fresh cached result and unsupported (non-http(s)) URLs resolve immediately, while the rest are checked asynchronously: the submission enqueues an execution request on a new Kafka topic and a FastStream consumer runs the checks. The endpoint returns the created check resource as the body and its URL as theLocationheader: a submission whose URLs all resolve immediately completes at submission and is returned with status 200 (no polling needed), while a submission with URLs to check returns 202 and should be polled at theLocationheader (or the body’sself_url).GET /ook/linkcheck/checks/{id}reports the check’s processing status (pending/in_progress/complete), summary counts by URL status, and per-URL results (status, HTTP status code, redirect location). Only default-version submissions replace an origin’s recorded URL occurrences; PR-build submissions still receive full results. Link health is tracked per canonical URL across origins with a failing-to-broken retry ladder, so a previously-OK link is only declared broken after repeated failures over a configurable window.Added anonymous read endpoints for link health.
GET /ook/linkcheck/urls?url=...looks up a single canonical URL’s stored record: its status, HTTP status code, redirect location, check timestamps, and the origin pages it occurs on (the lookup URL is canonicalized first).GET /ook/linkcheck/links?origin=...lists an origin website’s links with their health states and page paths, with keyset pagination (LinkandX-Total-Countheaders) and astatusfilter:?status=redirectedlists links whose sources should be updated to their new locations, and?status=brokenis the rot-monitoring view.Added a new
ook linkcheck-recheckCLI command, intended to run as a daily cron job. It enqueues URLs that are due for a recheck and still occur on at least one origin page as batchedRecheckUrlsMessageKafka messages (the Kafka consumer re-checks them and advances their statuses through the retry ladder — this is how a failing link progresses to broken over subsequent days). The command also purges link-check maintenance state: check records older than the retention period and URL records with no remaining page occurrences and no membership in a retained check.New configuration settings for link checking:
OOK_LINKCHECK_KAFKA_TOPIC(defaultook.linkcheck),OOK_LINKCHECK_REQUEST_TIMEOUT,OOK_LINKCHECK_MAX_CONCURRENCY,OOK_LINKCHECK_HOST_INTERVAL,OOK_LINKCHECK_FRESHNESS_TTL,OOK_LINKCHECK_MAX_URLS_PER_CHECK, andOOK_LINKCHECK_CHECK_RETENTION(default 30d, the age beyond which check records are purged byook linkcheck-recheck). The failing-to-broken retry ladder is tunable throughOOK_LINKCHECK_BROKEN_THRESHOLD(default 48h),OOK_LINKCHECK_BROKEN_MIN_ATTEMPTS(default 3), andOOK_LINKCHECK_RECHECK_INTERVALS(default 1h, 4h, 24h, 48h).
Bug fixes#
Adapt the SDM links domain endpoint to FastAPI 0.137’s nested route tree by using
url_path_forinstead of iteratingapp.routes. FastAPI 0.137 nests routes added viainclude_routerinside intermediate router objects, so the previous flat iteration overapp.routesno longer found the SDM link routes and the/ook/links/domains/sdmendpoint raised aKeyError.The service start-up script no longer runs
ook init. Runningook initon every pod start stamped the database at the current Alembic head revision without running migrations, so pending migrations were silently skipped: the pre-deploymentupdateSchemajob then saw an up-to-datealembic_versionand no-oped while the actual tables kept their old shape, and the application’s schema-currency check passed against a stamp that was a lie. Schema changes are now applied only by the pre-deployment job (ook update-db-schema), and the application refuses to start if the database schema is out of date (the existingis_database_currentcheck at startup). Theook initcommand remains available for development bootstrap.Link-check execution is now idempotent under Kafka’s at-least-once delivery. Re-executing an already-complete check is a no-op, so a completed check is no longer briefly flipped back to
in_progress(with a staledate_completed) while a redelivered execution request re-runs it. A check leftin_progressby a crashed prior execution is still re-executed to completion on redelivery.Hardened the link checker’s SSRF guard against DNS rebinding. Link-check HTTP requests now connect to the exact address the SSRF guard validated, pinning the socket to that IP while preserving the original hostname for the
Hostheader and for TLS SNI and certificate verification. Previously the guard resolved and validated the host, but httpx independently re-resolved the hostname when connecting, so a low-TTL or rebinding DNS answer could return a public address to the guard and a private one to the connection a moment later. This time-of-check-to-time-of-use gap (applied to the initial URL and to every redirect hop) is now closed.Document ingest is now idempotent by natural key. ID minting moved out of the request model and into the storage layer, inside the ingest transaction: an incoming document is resolved against existing rows by matching the database’s document-identity unique constraints in turn —
handleondocument_resource, then(series, number), thendoionresource— so a match keeps its ID and takes the update path. Re-ingesting the same payload no longer creates duplicate rows or fails on a unique constraint, and re-ingesting with changed fields (including a changed series or handle) updates the resource in place under the same ID.Genuinely new documents now mint a time-ordered ID (via the
ook.domain.base32idgenerator) so freshly ingested resources sort in creation order under the default ID-keyset listing. The new row is inserted withON CONFLICT (id) DO NOTHINGand retried with a fresh ID on a random collision, so a collision can never silently merge two resources. Ingest timestamps are now stamped in UTC.Document ingest now processes each document in its own savepoint and reports its outcome individually. A single malformed document no longer 500s the whole batch or is silently dropped: it is reported as
failedwith an error detail while the remaining documents are stillcreatedorupdated. Thecreatedvsupdateddistinction reuses the natural-key resolution so a document matched to an existing resource reportsupdated.External references cited by documents now dedup on any identifier they carry. The DOI-less
ON CONFLICT (url)upsert path previously raisedProgrammingErrorbecause no unique index backed theurlcolumn; a partial unique index on non-null URLs fixes it. References keyed only by an arXiv ID, ISBN, ISSN, or ADS bibcode now upsert on that key instead of violating its unique constraint when re-cited. References with no identifier at all (no DOI, arXiv ID, ISBN, ISSN, bibcode, or URL) are now rejected at ingest and by a database check constraint, so unmergeable duplicates can no longer accumulate.Duplicate resource relation edges are now rejected by the database. The previous whole-row unique constraint on
resource_relationwas a no-op under PostgreSQL’s defaultNULLS DISTINCTsemantics (one of the two related-entity columns is always NULL, making every row distinct); it is replaced by two partial unique indexes, one per edge kind. Supporting indexes were also added for reverse relation lookups (related_resource_id,related_external_ref_id), relation-type filtering ((source_resource_id, relation_type)), and contributor-by-author queries (contributor.author_id).
Other changes#
Ook now runs on Python 3.14. The Docker image is based on
python:3.14.6-slim-bookworm, the minimum supported Python is now 3.14, and the development environment and CI test against Python 3.14.Introduced a Snowflake-style time-ordered ID generator for resource IDs in
ook.domain.base32id(generate_resource_idandmint_resource_id_for_timestamp). IDs pack 43 bits of milliseconds since a fixed 2010-01-01 epoch into the high bits plus 17 random low bits, staying within the existing 60-bit / 12-character Crockford Base32 envelope so the API format and serialization are unchanged. The epoch is deliberately non-configurable and predates all Rubin Observatory record-creation dates, so other services can adopt the scheme (and re-mint existing tables) without per-service epoch configuration. Document ingest mints these IDs for new resources, and existing IDs are re-minted by this release’s migration, so resource listings under the default ID-keyset ordering follow creation order.
0.22.0 (2026-06-10)#
New features#
Added author internal ID aliases so that two authordb.yaml IDs that correspond to the same person (and therefore the same ORCID) can coexist. An alias resolves to its root author:
GET /ook/authors/{internal_id}with an alias returns the root author’s record, document ingests attribute contributors referencing an alias to the root author, and the lsst-texmf ingest skips authordb.yaml entries whose keys are registered aliases instead of failing on a duplicate ORCID. Aliases are managed through new admin endpoints:GET /ook/admin/authors/aliases,POST /ook/admin/authors/aliases(with analias/canonicalrequest body), andDELETE /ook/admin/authors/aliases/{alias}. Creating an alias for an internal ID that already exists as an author record merges that record into the root author, re-pointing existing document attributions.
Bug fixes#
Factory.create_standalonenow stops the Kafka broker when its context exits. Previously the broker (a module-level singleton shared with the FastAPI app’s Kafka router) was left connected, leaking aiokafka producers bound to the event loop that created them. In the test suite this caused an “Event loop is closed” error during app shutdown whenever a test using the standalonefactoryfixture ran before a handler test in the same pytest invocation.
0.21.0 (2025-10-28)#
New features#
Added Slack webhook notifications for lsst-texmf author ingest issues. When the
OOK_SLACK_WEBHOOKenvironment variable is configured, Ook now sends notifications for:Stale author entries: When author IDs are renamed in lsst-texmf’s authordb.yaml, the old entries that remain in Ook’s database are detected and reported (without automatic deletion).
Duplicate ORCID violations: When an author ID changes but keeps the same ORCID, causing a unique constraint violation, a detailed notification is sent with information about both the existing and new author entries, including likely causes and resolution steps.
Added admin API endpoint
DELETE /ook/admin/authors/{internal_id}for manually deleting author entries when resolving stale entries or ORCID conflicts. These admin endpoints are intended to be protected with Gafaelfawr scope such asexec:internal-tools.Ook’s docker images are now built for both amd64 and arm64 architectures.
Bug fixes#
The UTF-8 BOM is now properly handled when reading CSV files for glossary ingest, preventing parsing errors.
Other changes#
Improved testcontainers setup for compatibility with Colima on macOS.
0.20.0 (2025-08-07)#
Backwards-incompatible changes#
This version adds a new
address_country_codecolumn to theaffiliationtable. This requires an Alembic migration,c03d146610d8to8e529b9177a0.
New features#
Ook now stores the two-letter ISO 3166-1 country code for an affiliation in the
affiliationtable, in addition to storing the country as provided byauthordb.yaml. When a country code is available, it is used for determining the affiliation’s country name, with a fallback to the country name column when absent. This should add reliability to affiliation address data.The new CLI command,
ook migrate-country-codesmigrates existing country names to the country codes column.Added formatted address field to affiliation responses. Affiliation addresses now include a
formattedfield that contains properly formatted address strings using international standards.Uses the google-i18n-address library to respect country-specific conventions for address layout
Includes graceful fallback formatting for invalid or incomplete address data
Maintains full backwards compatibility with existing API consumers
0.19.0 (2025-08-04)#
Backwards-incompatible changes#
A database migration is required to add a new
search_vectorcolumn to theauthortable. This column enables full-text search capabilities and is populated with computed values from thegiven_nameandsurnamefields. Requires Alembic migration from1ad667eab84etoc03d146610d8.
New features#
The
/authorsendpoint now supports asearchquery parameter that allows for flexible and typo-tolerant searching of authors by name. The search system automatically detects and handles various name formats:“Last, First”
“Last, Initial”
“First Last”
Family name only
Given name only
Compound family names
Names with suffixes
Partial names, initials, and typos
Other changes#
Improved codebase compatibility with coding agents like Claude:
Streamlined the logging output from
noxtests to reduce noise.Added Claude context file (
CLAUDE.md) with project instructions.
0.18.0 (2025-07-29)#
Backwards-incompatible changes#
This release requires a database migration to add new tables for the resources API:
113ced7d2d29to1ad667eab84e.
New features#
Ook now has a bibliographic resource API for storing metadata records about Rubin Observatory documentation (technical notes, documents, user guides), software code bases, and other resources:
Core data model designed to be compatible with DataCite concepts for straightforward integration with DataCite DOI registration.
Polymorphic resource model allows different types of resources (documents, software, datasets) to be stored efficiently. This release demonstrates this model with a
Documentresource type.Support for relationships between records and external references (such as papers with DOIs). Relationships are annotated with DataCite relationship types to enable features such as reference tracking and tracing documents that supersede other documents.
Integration with the existing author API for both author lists and tracking other types of contributors.
Resources are available through
GET /resourcesandGET /resources/{id}endpoints. These endpoints should be considered experimental and subject to change in future releases.
This bibliographic API will enable features such as sophisticated documentation search APIs and user interfaces, automation for DOI registration, and more. Future releases will integrate Ook’s existing documentation ingest processes with the bibliographic database and develop API endpoints for querying and managing bibliographic resources.
0.17.0 (2025-07-15)#
Backwards-incompatible changes#
Dropped the
collaborationtable from the database schema and removed related code from the application. Originally in Ook we wanted to treat human authors separate from pseudo authors in order to make building out a staff directory easier. However, working against the grain of authordb.yaml (the canonical source for Rubin author data) has proven to be difficult. Now collaborations/collective authors will appear in the/authors/endpoints and in theauthordatabase table.Requires database migration,
113ced7d2d29.
0.16.0 (2025-07-11)#
New features#
Handle the parsing exception when a LaTeX (Lander) document’s articleBody metadata is still LaTeX-formatted rather than the excepted Markdown conversion. The metadata parser still creates a content chunk for Algolia consisting of the title and description/abstract.
Handle parsing Technote (Sphinx) technotes where the abstract directive is missing. The metadata parser now returns a default message indicating that the abstract is not available.
Other changes#
Adopt nox-uv for installing dependencies in
noxfile.py.
0.15.0 (2025-07-07)#
Backwards-incompatible changes#
The author resources in the REST API have the following changes:
The
surnamefield is nowfamily_nameto better match common usage.The affiliation metadata is no longer a simple string, but instead a structured object with address components.
A database migration is required (Alembic migration
176f421b2597).
New features#
In addition to the backwards-incompatible changes related to the author
family_namefield and affiliationaddress, the authors API now includes the ROR ID for affiliations and the department name for an affiliation, where appropriate. Ook now reflects the structure of lsst/lsst-texmf’sauthordb.yamlfile as of 2025-07-05.
0.14.0 (2025-06-23)#
Backwards-incompatible changes#
Changed the
GET /authors/id/{id}endpoint to now beGET /authors/{id}to align with the other endpoints in the API.Changed SQL table names to be singular instead of plural. This change requires a database migration (Alembic migration
fb5ed49d63d5).
New features#
The
POST /ingest/lsst-texmfendpoint (andook ingest-lsst-texmfcommand) provides an option to delete author records that are no longer present inauthordb.yaml. This is not the default behavior.
Bug fixes#
Collaborations are now filtered out from the
/authorsendpoint. We may add a new collaborations endpoint in the future.Terms in
glossarydefs.csvare deduplicated before being added to the database. This prevents duplicate terms in the CSV, a common typo, from preventing the ingestion of the glossary definitions.
Other changes#
Dropped the
nox init,init-venv, andupdate-depssessions in favor of Makefile targets to reduce subtle issues about hownoxdepends onuvin thenoxcontext.
0.13.1 (2025-04-30)#
Bug fixes#
The database session is now committed after running
ook ingest-lsst-texmf.
0.13.0 (2025-04-30)#
New features#
Added a new Author API to interact with author metadata records from Rubin Observatory’s author database, which is canonically maintained as the
etc/authordb.yamlfile in lsst/lsst-texmf.Use the new endpoint
GET /ook/authorsto paginate over all author records. Author records include affiliations.Use
GET /ook/authors/id/{internal_id}to retrieve the record for a single author based on their author ID.
Added a Glossary API to interact with the Rubin Observatory glossary, which is canonically maintained in the
etc/glossarydefs.csvandetc/glossarydefs_es.csvfiles in lsst/lsst-texmf.The
GET /ook/glossary/search?q={term}endpoint allows searching for glossary terms. The search is case-insensitive and typo-tolerant.
A new ingest endpoint,
POST /ook/ingest/lsst-texmftriggers a refresh of author and glossary data from thelsst/lsst-texmfrepository. This service can also be run from the CLI with theook ingest-lsst-texmfcommand (useful for testing or cron jobs).
Bug fixes#
Fixed the AsyncAPI documentation generation (available at
/ook/asyncapi).
Other changes#
Migrated dependency management to UV lockfiles, with dependencies defined in pyproject.toml’s
dependenciesarray anddependency-groupstable. In addition to deleting the oldrequirements/files, this change also affects the Dockerfile, GitHub Actions, and Nox setup (noxfile.py).Adopt Python 3.13.
Fixed the process for creating Alembic migrations, ensuring that the previous database schema is mounted correctly.
The FastStream lifecycle is no longer explicitly managed.
0.12.0 (2025-04-16)#
New features#
The Links API collection endpoints now use pagination for improved performance and usability. Ook uses keyset pagination, so look for a Links header with
next,prev, andfirstlinks. Use these URLs to advance to the next page. TheX-Total-Countheader indicates the total number of items in the collection. Pagination applies to the following endpoints:GET /ook/links/domains/sdm/schemasGET /ook/links/domains/sdm/schemas/:schema/tablesGET /ook/links/domains/sdm/schemas/:schema/tables/:table/columns
0.11.0 (2025-04-04)#
New features#
New Links API, available at
/ook/links, that provides documentation links to Observatory and survey entities across different domains. This Links API is described in SQR-086. Initially the Links API supports links to documentation about the Science Domain Model (SDM) schemas, tables, and columns.A new endpoint,
/ook/ingest/sdm-schemastriggers an ingest of links for schema, table, and column entities in the lsst/sdm_schemas repository to targets in https://sdm-schemas.lsst.io. This endpoint is being developed towards the creation of a links API service, see SQR-086.
Other changes#
Adopt Faststream 0.5, dropping an earlier pin on Faststream 0.4.
Adopt UV in the Docker build.
Ook now uses a Postgres database to maintain datasets. Initially Postgres tables are used to store the SDM schemas as well as links for the Links API. The Postgres database is managed by Alembic, and the database schema is maintained with SQLAlchemy. The
OOK_DATABASE_URLandOOK_DATABASE_PASSWORDenvironment variables configure the connection to this database.The nox
runsession can now run with roundtable-dev credentials from 1Password for testing the application locally. Seesquare.envfor details.
0.10.0 (2024-08-14)#
New features#
Ook now uses faststream for managing its Kafka consumer and producer. This is also how the Squarebot ecosystem operates. With this change, Ook no longer uses the Confluent Schema Registry. Schemas are instead developed as Pydantic models.
Other changes#
Use
uvfor installing and compiling dependencies innoxfile.py.Update GitHub Actions workflows to use the lsst-sqre/run-nox GitHub Action.
Adopt
ruff-shared.tomlfor shared Ruff configuration (from lsst/templates)Update Docker base to Python 3.12.5-slim-bookworm.
Switch to testcontainers for running Kafka during test sessions. The Kafka brokers is automatically started by the
noxsessions.
0.9.1 (2024-01-29)#
Bug fixes#
If a technote doesn’t have the
og:article:modified_timethen Ook falls back to using the current time of ingest. This fallback is to meet the schema for the www.lsst.io website, and ideally documents should always set modification time metadata.
0.9.0 (2023-09-26)#
New features#
Added support for ingesting Technotes (as generated with the technote.lsst.io framework). These technotes are generated with Sphinx, but embed metadata in common formats like Highwire Press and OpenGraph. This new technote format replaces the original technote format, although the original technotes are still supported by Ook.
0.8.0 (2023-09-06)#
New features#
Add a new
ook ingest-updatedcommand to queue ingest tasks for all LTD projects that have updated within a specified time period. This command is intended to be run as a Kubernetes cron job. Once push-based queueing from LTD is available on the roundtable-prod Kubernetes cluster this command can be deprecated.
0.7.1 (2023-09-05)#
Bug fixes#
Improved and logging and exception reporting around the
ook auditcommand.Fixed the
base_urlattribute’s JSON alias for the Algolia DocumentRecord model. WasbaseURLand is now restored tobaseUrl.Fix typo in creating records for Lander content types (
source_update_timeandsource_update_timestampfields).
0.7.0 (2023-08-31)#
New features#
The new
ook auditcommand (and associatedAlgoliaAuditService) audits the contents of the Algolia index to determine if all documents registered in the LSST the Docs API are represented in the Algolia index. This command can be run asook audit --reingestto automatically queue reingestion jobs for any missing documents.
Bug fixes#
Fixed the CLI entrypoint from
squarebottoook.
Other changes#
The Factory is refactored. A
ProcessContextnow holds singleton clients for the duration of the process, and is used for both the API handlers and for worker processes, including CLI instantiations of Ook as Kubernetes jobs. This new architecture moves configuration of Kubernetes and registration of Kafka Avro schemas out of the main module and into the factory instantiation.The Algolia search client is now mocked for testing. This allows the new factory to always create a search client for the process context. It also means that Algolia client credentials are always required; the test configuration uses substitute keys for the mock.
0.6.0 (2023-07-20)#
Backwards-incompatible changes#
The app is rewritten as a FastAPI/Safir app, replacing its heritage as an aiohttp/Safir app. The app is also now deployed with Helm via Phalanx Because of this, Ook should be considered as an entirely new app, with no backwards compatibility with the previous version.
Ook no longer receives GitHub webhooks; the intent is to get GitHub webhook events from Squarebot (through Kafka) in the future.
Ook no longer receives Kafka messages from LTD Events since that app isn’t avabile in the new Roundtable deployment. A new ingest trigger is being developed in the interim. Until then, ingests can be manually triggered by the
POST /ook/ingest/ltdendpoint.
New features#
Ook is now a FastAPI/Safir app.
Ook uses Pydantic models for its Kafka message schemas.
Ook is now built around a service/domain/handler architecture, bringing it in line with SQuaRE’s modern apps. The Kafka consumer is considered a handler.
Add
ook upload-doc-stubCLI command to manually add a single record to Algolia to stub a document into the www.lsst.io search index. This is useful for cases where a document can’t be normally indexed by Ook.
Other changes#
The change log is maintained with scriv
Tests are now orchestrated through nox.
0.5.0 (2021-12-01)#
New features#
Compatibility with “main” as the default branch when sorting and detecting
technotemetadata.yaml files.
0.4.0 (2021-09-13)#
New features#
Documents are ingested with a new
sourceCreationTimestamp. This timestamp corresponds to the time when a document was initially created. A new workflow,get_github_creation_datecan be used to infer this creation date on the basis of the first GitHub commit on the default branch that was not made bySQuaRE Bot(or any email/name corresponding to a bot) during the initial template instantiation.Ook is now configured as a GitHub App.
0.3.1 (2021-03-02)#
Bug fixes#
Added hardening to the Kubernetes deployment manifests
0.3.0 (2020-07-17)#
New features#
Improved ingest reliability:
For Lander (PDF) content, added a heuristic that rejects TeX that Pandoc might let through.
Handle AASTeX technotes that don’t have full Lander site. Specifically, AASTeX technotes don’t include the handle in the TeX source, so instead we use the document’s URL.
If a Lander site doesn’t have an abstract, we fall back to using the first content chunk.
Support Lander docs without content
Support Sphinx technotes that include content before the first subsection header.
Improved logging during ingests, including logging of records when an insertion into the Algolia index fails.
0.2.0 (2020-07-02)#
New features#
Support for sorting documents:
The
numberrecord field is now numeric, supporting sortable document handles.The new
sourceUpdateTimestampis the integer Unix timestamp corresponding to when the document was updated. This timestamp supports sorting documents by their update recency.
After ingest, old records for a URL are deleted. This expiration is done by searching for records for a given
baseUrlthat have asurrogateKeyvalue other than that of the current ingest.In development environments,
make testnow runs Ook through its tox configuration.Refreshed all pinned dependencies
0.1.0 (2020-06-18)#
New features#
First release of Ook!
This release includes support for classifying and ingesting both Lander-based PDF documents with JSON-LD metadata and Sphinx/ReStructuredText-based HTML technotes.
This release also includes a full Kustomize-based Kubernetes deployment manifest.