Repository navigation
Releases
v0.9.1
Fixed
-
A replica that starts while another runs the migrations waits for
it, up to 5 minutes, where it refused to start on the migration it
found in progress. -
A huge
Retry-Afterfrom the key service is a long wait, no longer
one that wrapped to negative, and a date in it is waited for. -
A request id is passed to the authorizer only when it is printable and
at most 128 bytes. A request without one, or with another, gets a
fresh one.
Release evidence
- Tag:
v0.9.1 - Commit:
a1703b064f878a38d1f7e4ef93b78e32d9734314 - Deploy: https://github.com/latere-ai/lectio/actions/runs/42092773787
- Origin: https://api.latere.ai/v1/parsing
- Served version:
v0.9.1(the Lectio-Version header) - Smoke:
/openapi.yamlanswered 200,/readersanswered 401 with no bearer
v0.9.0
Added
- A release can deploy itself. The release workflow has a
deployjob
between the build and the publish, which appliesdeploy/prodwith both
images pinned by digest, waits for the three Deployments and runs
tools/smoke/release.shagainst the live origin. It runs only where the
repository variableLECTIO_RELEASE_DEPLOYis set, so a fork publishes
every artifact and deploys nothing.deploy/prodholds the maintainer's
production manifests anddeploy/prod-bootstrapthe identity the job
deploys with. Neither is part of the install path or of the
deploy-<tag>.tar.gzarchive of a release.
Changed
- Releases are built, signed and published by the shared release stages
in latere-ai/ci. The signatures on both images and on the signed
checksums.txtnow name those stages, run for this repository.
SECURITY.md gives the commands that check a release, and the ones for
releases up to v0.8.2; the release workflow runs the checks against
every release it publishes.
Release evidence
- Tag:
v0.9.0 - Commit:
ddcba2aeb7259fdb5e89c1ea2672c34cadbc70d7 - Deploy: https://github.com/latere-ai/lectio/actions/runs/42048808594
- Origin: https://api.latere.ai/v1/parsing
- Served version:
v0.9.0(the Lectio-Version header) - Smoke:
/openapi.yamlanswered 200,/readersanswered 401 with no bearer
v0.8.2
Fixed
- Built with Go 1.27.3, which fixes GO-2026-6809, a flaw in the
standard library's certificate verification that this code can reach.
v0.8.1
Fixed
lectiodexports its telemetry. WithOTEL_EXPORTER_OTLP_ENDPOINT
set, the API and the worker start the OpenTelemetry export: a span and
the request metrics (http.server.request.durationand the body sizes)
for every request of the API but/healthz, the spans of the outbound
calls to a model endpoint, a converter and a source URL, the log, and the
Go runtime's metrics. Before, those calls went through a tracing transport
with no exporter behind it, so a deployment that set the endpoint
exported nothing. The log keeps its JSON format, and each record now
carriesservice,versionandreplica.
v0.8.0
Added
- Every answer names the release that wrote it. The API sets the
response headerLectio-Versionon everything it answers on
LECTIO_ADDR, errors,/v1/openapi.yamland/healthzincluded: the
versionlectiod versionprints and the internal/versionreports,
such asv0.8.0, ordevfor a build that was not stamped. A caller
comparing results across releases reads which one answered from the
answer itself, which during a rolling update is the only place that
says. A proxy that should not reveal the release removes the header.
v0.7.1
Fixed
- Thirteen descriptions in the API contract read in full. Inside a flow mapping an unquoted description ended at its first comma, and the rest of the sentence became a stray key: the width of a page read "Points for paged formats", and fields and sets named a key for the tail of their extractor's sentence. They are quoted, and a test holds the contract to having no such remainder.
v0.7.0
- Added:
DELETE /sets/{set}/parses/{parse}takes a parse out of a set
and leaves the parse. Its extraction under the set's name stays on the
parse with its values, as an extraction of no set; the set no longer
counts or lists it, and a change of the set no longer asks it. A later
join takes it back in without a model call while it was asked with the
set's definition. It isconflictwhile that extraction has not ended,
and asksset.update. - Added: an extraction names the set that asked it,
set, and the
version of the set's definition it was asked with,set_version, on
every read. Both are absent on an extraction no set asked, and once its
set is deleted or its parse leaves it. - Added: the answer of
PUT /sets/{set}/parses/{parse}carriesasked,
truewhen the join asked the extraction, as its status202says. - Migration 000009 adds one function and changes no table.
- Added: readers changed while the server runs.
PUT /readers/{name}
stores a reader, its body thespecof a Reader document in JSON;
DELETE /readers/{name}removes one;PUT /policysets the order the
readers are tried in, in the place of the configured Policy, and
DELETE /policyputs that back;GET /readers/{name}and
GET /policyread them. Every process of the durable server reads
with the change withinLECTIO_READERS_POLL(10 seconds), with no
restart, and the process that made it at once. A stored reader reaches
one ofLECTIO_READER_ENDPOINTS, by default the endpoints the
configured readers reach; the stub adapter is refused, and a
configured reader is never changed. A reader the order names, one a
set's definition names, and one with work that has not ended are not
removed. - Added: the actions
reader.updateandreader.delete. The owner
policy allows them toLECTIO_ADMIN_SUBJECTSalone. An authorizer
that does not know them refuses these routes and nothing else. - Added:
GET /readerssays of each reader where it came from
(source), itsadapter, itsmodel, and whether itdescribes
andextracts. - Added:
readeron an allow, the default reader of a caller. A
submit, a figure run, an extraction and a set's definition that name
none are read with it, as if they named it, where it does what is
asked; one the server does not have isreader_not_found. - Added: a key ask names
models, the models the readers in force
reach, and a worker holds a key per group and per that list. - Changed: a task that waits at a place of a chain that a new
configuration makes shorter waits at the chain's last place, where it
waited for a place nobody reads. - Migration 000010 adds the tables
readersandreader_policyand
replaceslectio_configure; it touches no table in use.
v0.6.1
- Changed: the summary of
PUT /sets/{set}/parses/{parse}in the
contract reads "Add a parse", short enough for a reference's
navigation, which lists it under its tag,sets.
v0.6.0
- Added: sets. A set is a name and the definition of an extraction,
made before any file is read (POST /sets), and asked of each parse
that joins it (PUT /sets/{set}/parses/{parse}). A parse whose
extraction of the name was already filled with the set's definition
joins without a model call.PUT /sets/{set}changes the definition
and asks every parse of the set again, and is refused withconflict
while one of its extractions is queued or running; the definition the
set already holds, sent again, asks nothing.
GET /sets/{set}/parsesreads a set's table, every parse with its
extraction, in one request. Deleting a set leaves its parses and their
extractions. A set holds at most 10,000 parses. - Added: the
Setkind and the actionsset.create,set.read,
set.list,set.updateandset.delete. An authorizer that does not
know them refuses the set routes and nothing else; the allows of
set.createandset.updateare read forownerandreaders. - Added: the error code
set_not_found. - Changed: an extraction a set asked is asked again by name
(PUT /parses/{parse}/fields/{name}) with the set's request alone,
compared as a JSON value; another request isconflict. - Migration 000008 adds the
setstable and two columns tofields. It
takes the lock offieldsas 000007 does, and its down file keeps the
extractions a set asked as extractions of no set.
Security
- Built with Go 1.27.2 and golang.org/x/net v0.60.0, which fix GO-2026-6611, GO-2026-6612, GO-2026-6613 and GO-2026-6617.
v0.5.1
- Fixed: a
uniqueItemscheck of a list too costly to hash is answered
as not checked before any item is hashed, so the answer takes no
longer than reading the list. v0.5.0 hashed such a list first, which
a list of a megabyte made take seconds on a slow machine.
v0.5.0 - 2026-10-06
Its tag was cut and its release pipeline stopped before it published, so its changes are released here.
-
Changed: a
uniqueItemscheck of a list of more than 20 items is
priced by the comparisons the validator makes, which are the pairs of
items whose hashes are equal, and no longer as if every item met every
other. A list of distinct objects is checked up to 65,535 small
items, where it was refused past about 500; items built to hash alike
are still priced past the bound and not checked. -
Added:
GET /readersmarks a reader that reads a page from the text
its file carries and calls no model withtext_layer: true, so a
console can keep it out of a picker of models while the routing
policy still tries it first. -
Fixed: an extraction no longer reads page furniture. Blocks of kind
page_header,page_footerandpage_numberare left out of the
text a model is given and out of what a citation may name, so a
running header is not taken for the document's title. -
Added:
PUT /parses/{parse}/fields/{name}asks an extraction again
under its name, with another schema or with the same one after it
failed. Only an extraction that has ended is asked again; one that is
pendingis409 conflict. It is reset topendingwith the new
request and nothing of its last result, the result it replaced is
removed, and its task is queued as a new extraction's. A name the
parse has no extraction of is asked as a new one. Migration
000007_ask_againadds a count of askings to an extraction. Pods of
v0.4.0 that are running keep working beside it; one that starts after
it does not come up, so roll every role.