Command line interface for accessing the Open Web Index shards and slices.

fix(http,core): return the descriptive record, and fix two accessors that hid it master

Three findings from the openwebindex.eu dashboard, each reproduced against live data before anything was changed. Ask 1 -- /remote/ls?include=metadata. Each listing row was hand-built from eleven fixed keys while ds.metadata carried 38-43, so the descriptive record was retrieved, carried onto the Dataset, and dropped one function before the response. The fix sources as_json_dict(), which returns native values rather than display renderings: against the real German Commons record, 8 creators with ORCIDs where get() said "Lukas Gienapp+7", a 1,385-character description where get() truncated, and a licence where get() returned None. Swept as_json_dict() over all 1,864 LEXIS records: zero failures across all six shape variants. DataCite fields are nested under a `datacite` key -- stating the shape, since either was acceptable and the reporter had already written a parser for that one. Opt-in, absent fields omitted rather than nulled, nothing keyed on a fixed key set, and a record that cannot be rendered reports metadata_error while the page still answers. No re-pull or migration required. Ask 2 -- DatasetMetadata was not a usable mapping. keys() advertised six fields __getitem__ refused, so dict(md), {**md} and md.items() failed on exactly the records that legitimately lack one. Advertised-but-absent now returns None, agreeing with .get(); an unadvertised key still raises. Reachable from owilix itself: cli/_common/output.py calls dict(d.metadata). A third bug fell out of it. RightsListMetadata.short_repr() indexed r['rightsIdentifier'], which DataCite does not require, and .get() swallowed the KeyError -- so metadata.get("rightsList") answered None for exactly the datasets that publish a real licence. Now falls back identifier -> rights -> uri. Ask 3a -- response models for the listing endpoints. 0 of 46 200-responses declared a schema, which is why dropping thirty fields was invisible to the OpenAPI, to generated clients and to schema-level tests. Validators coerce rather than reject, so declaring types cannot make a listing fail on one odd record -- the guarantee this API has spent several releases earning. Ask 3b -- require_auth renamed to require_upstream_session, alias kept. The old name promised caller authentication it never performed. The wire error code stays auth_required because callers branch on it; the clarification goes in a new message field, and the docs now say plainly that anything reaching the port can drive every route. Two mistakes made and caught here, both recorded: declaring the model initially emitted metadata: null on every row, which is the null-filling the report asked us to avoid; and two workflow tests written yesterday pinned a fixture date against a relative window, so they passed when written and failed the next morning looking like an unrelated regression. Not addressed, deferred by the reporter: /health cannot fail, and /remote/ls pagination re-walks the backend per page with no cache. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017phbSd6D8u4iEQsCAPEw6s