Commit Graph
13 Commits
Author SHA1 Message Date
ajandClaude Opus 5.5 be057bf337 feat(server): store versioned drawing sets
A drawing set is a named list of library drawings with quantities (a kit,
an assembly, a recurring order) that will later be released into one nest
per material. This is the server half: sets get the same revision,
If-Match and archive contract as /api/drawings so the client and tests
follow a known shape.

Schema v7 adds drawing_sets, drawing_set_revisions and
drawing_set_members. Members reference drawings by id and mean each
drawing's current revision, so reads join the current drawing record:
the client can group members by material without one request per drawing,
and the joined record is ignored on save so a read record can be sent
back unchanged. Every change keeps its own member list, and
/api/drawings/{id}/sets answers "used in" from current revisions only.

The drawing query's enum, integer and history-paging parsing is now shared
so both APIs refuse bad input identically.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 12:51:56 -04:00
ajandClaude Opus 5.5 3bc71a7e87 feat(server): allocate nest names from one yearly server sequence
File > New restarted its counter every day while names only carry the
year, so the first nest of each day was always N26-223, and each PC kept
its own counter. In Database mode the nest server now hands out the
year's next number (POST /api/nest-names/next, nest_sequences table,
schema v6), staying above every stored generated name so offline or
pre-existing names are never reissued. The per-PC counter remains the
fallback when the server is unreachable or older, resets per year, and
is raised past each server allocation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 11:09:07 -04:00
ajandClaude Opus 5.5 5dff83cfb8 fix(server): reject duplicate nest ids, invalid metadata and bare --database
- POST /api/nests with an existing id (active or deleted) now returns 409 with
  the current record instead of a 500 from the UNIQUE constraint.
- Uploaded nest metadata must have string text fields and a defined status;
  null fields and undefined statuses (e.g. 99) are 400 instead of a 500 or a
  stored invalid value.
- --database <path> is accepted alongside --database=<path>; a missing or
  repeated path fails startup instead of silently using OPENNEST_DB/default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:30:37 -04:00
ajandClaude Opus 5.5 76133193df feat(server): drawing library schema and routes
The server becomes the system of record for shared drawings (cut type,
thickness, material and grade, customer, notes). Schema v4 adds `drawings`
(current row) and `drawing_revisions` (immutable) to the same SQLite file under
the existing monitor; the nest tables are untouched and a v3 upgrade keeps every
nest row byte-identical.

`/api/drawings` follows the nest revision contract: client-allocated ids,
If-Match on every existing-drawing write (428/400/409 with no state change),
archive instead of delete, and one transaction for promotion plus snapshot.
Geometry is an opaque package (a zero-plate .nest) the server never parses.
Enum fields accept single names only, because the JSON enum converter would
otherwise accept numbers and comma combinations. Material, grade and customer
filters match SharedListNames keys so spacing and case cannot split a drawing
family; thickness is stored and compared at four decimals.

Shared bounds live in OpenNest.Data so the client can refuse the same requests
before sending. If-Match parsing moves to one helper used by nests and drawings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:33:02 -04:00
aj 914c197181 feat(server): restore historical nest as new revision 2026-10-11 16:49:12 -04:00
aj 5598804942 feat(server): preserve deleted nests with guarded recovery 2026-10-11 16:49:12 -04:00
aj d216bcd406 feat(server): version guarded metadata edits 2026-10-11 16:49:12 -04:00
aj a47b414392 feat(server): preserve file-save nest revisions 2026-10-11 16:37:28 -04:00
aj 1fadf6c4d3 feat(server): add bounded nest query with SQL-side search
GET /api/nests/query filters name, customer, material, made by, comments
and status (stored and display names) with an escaped LIKE parameter,
orders newest saved first with an id tie-break, and returns one page of
at most 500 records plus the total match count, read in one database
hold. Unknown, repeated or out-of-range parameters return 400.

RemoteNestRepository.QueryAsync validates the same bounds before
sending, rejects oversized pages, and reports a 404 from an older server
as a server that needs updating. GET /api/nests stays the full
enumeration used by backup, restore checks and the container smoke.
2026-10-02 19:52:35 -04:00
aj 142c77a27f fix(server): serialize SQLite access and validate storage health 2026-10-02 16:31:46 -04:00
aj 5d8874a9e7 fix(server): reject malformed multipart uploads with 400 2026-10-02 15:48:55 -04:00
aj b17fe1a318 test(server): cover HTTP storage contracts with isolated SQLite 2026-10-02 15:37:44 -04:00
aj 437d659c9d feat(server): add OpenNest.Server SQLite nest storage API
SQLite-backed (Microsoft.Data.Sqlite, WAL) minimal API storing NestRecord
metadata plus the .nest archive as a BLOB. Endpoints: GET/POST /api/nests,
GET /api/nests/{id}[/file], PUT /api/nests/{id}/file, PUT
/api/nests/{id}/metadata, DELETE /api/nests/{id}, GET /healthz. Multipart
upload contract matches RemoteNestRepository (metadata JSON part + file
part). Added to OpenNest.sln, builds standalone on Linux. Dockerfile
publishes to a runtime image listening on :8090 with a /app/data volume
for the SQLite file. docs/nest-storage.md documents the wire contract,
endpoints and deployment.

Full curl round trip verified manually against a running instance:
upload (server-assigned id + computed fileSize), list, get, byte-exact
file download, metadata-only update (archive unchanged), file update
(new archive persisted), 404s for unknown ids, delete, post-delete 404.
2026-09-29 16:21:17 -04:00