Close the printers.metadata hole: not writable, not served

metadata was the way around the decision to hold no printer credentials.
It is a free-form jsonb column that was both writable through POST
/printers and listed in the public projection, so a client could stash an
access code in it and the API would store it and serve it back. Nothing
reads it: the frontend, the proxy and the dispatcher never touch
printers.metadata (dispatch's metadata is print_jobs', a different
column).

It is removed from PRINTER_WRITABLE and from printerProjection. The
column stays, so reopening it later is one line once something needs it,
ideally with a shape to match rather than free-form JSON.

The test that merely recorded the hole is replaced by one that asserts
it is closed at both ends, because a field nobody can read or one
nobody can write is still half of it: not in the projection, dropped
from a create body by Value.Clean, and absent from PRINTER_WRITABLE.

bun test 128 pass / 0 fail; e2e-authz.sh PASS with 68 checks.
This commit is contained in:
2026-10-29 10:13:28 +00:00
parent c72bfe71d6
commit 26d382b82d
3 changed files with 28 additions and 13 deletions
+20 -10
View File
@@ -6,7 +6,7 @@ import { startDevAuthIssuer } from "../scripts/dev-auth";
import { Value } from "@sinclair/typebox/value";
import { printers } from "../src/db/schema";
import { farmProjection, printerProjection } from "../src/db/projections";
import { PrinterCreateSchema } from "../src/db/validators";
import { PRINTER_WRITABLE, PrinterCreateSchema } from "../src/db/validators";
const USER = "11111111-1111-1111-1111-111111111111";
@@ -297,14 +297,24 @@ describe("credentials the backend must not hold", () => {
expect(Object.keys(farmProjection.columns)).not.toContain("edgeProxyToken");
});
test("metadata is the remaining way a secret could reach the cloud", () => {
// Not a bug to fix here, but a hole to know about: `metadata` is a
// free-form jsonb column that is both writable and in the public
// projection, so a well-meaning client could stash an access code in it
// and the API would store it and serve it back. Removing the dedicated
// column narrowed the door; it did not close it. If this assertion ever
// fails because `metadata` left the projection, that is an improvement -
// delete the test.
expect(Object.keys(printerProjection.columns)).toContain("metadata");
test("printer metadata is neither writable nor served, so it cannot carry a secret", () => {
// `metadata` was the way around the access-code decision: a free-form
// jsonb column that was both writable and in the projection, so a client
// could stash a credential in it and read it back. It is now closed at
// both ends. Pinned as three assertions because either end reopening it
// alone (a writable field nobody can read, or a readable one nobody can
// write) is still half of the hole.
expect(Object.keys(printerProjection.columns)).not.toContain("metadata");
const cleaned = Value.Clean(PrinterCreateSchema, {
farmId: "3f2b1c5e-0000-4000-8000-000000000000",
name: "P1P",
vendor: "bambu" as const,
metadata: { accessCode: "SECRET123" },
}) as Record<string, unknown>;
expect(cleaned).not.toHaveProperty("metadata");
expect(cleaned.name).toBe("P1P");
expect(PRINTER_WRITABLE as readonly string[]).not.toContain("metadata");
});
});