Add Milestones 1 & 2: full-stack POS foundation with admin UI

- Node/Express/TypeScript API under /api/v1 with JWT auth (login, refresh, logout, /me)
- Prisma schema: vendors, users, roles, products, categories, taxes, transactions
- SQLite for local dev; Postgres via docker-compose for production
- Full CRUD routes for vendors, users, categories, taxes, products with Zod validation and RBAC
- Paginated list endpoints scoped per vendor; refresh token rotation
- React/TypeScript admin SPA (Vite): login, protected routing, sidebar layout
- Pages: Dashboard, Catalog (tabbed Products/Categories/Taxes), Users, Vendor Settings
- Shared UI: Table, Modal, FormField, Btn, PageHeader components
- Multi-stage Dockerfile; docker-compose with Postgres healthcheck
- Seed script with demo vendor and owner account
- INSTRUCTIONS.md, ROADMAP.md, .claude/launch.json for dev server config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-20 23:18:04 -05:00
parent fb62439eab
commit d53c772dd6
4594 changed files with 1876068 additions and 0 deletions

125
server/node_modules/jws/lib/verify-stream.js generated vendored Normal file
View File

@@ -0,0 +1,125 @@
/*global module*/
var Buffer = require('safe-buffer').Buffer;
var DataStream = require('./data-stream');
var jwa = require('jwa');
var Stream = require('stream');
var toString = require('./tostring');
var util = require('util');
var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
function isObject(thing) {
return Object.prototype.toString.call(thing) === '[object Object]';
}
function safeJsonParse(thing) {
if (isObject(thing))
return thing;
try { return JSON.parse(thing); }
catch (e) { return undefined; }
}
function headerFromJWS(jwsSig) {
var encodedHeader = jwsSig.split('.', 1)[0];
return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary'));
}
function securedInputFromJWS(jwsSig) {
return jwsSig.split('.', 2).join('.');
}
function signatureFromJWS(jwsSig) {
return jwsSig.split('.')[2];
}
function payloadFromJWS(jwsSig, encoding) {
encoding = encoding || 'utf8';
var payload = jwsSig.split('.')[1];
return Buffer.from(payload, 'base64').toString(encoding);
}
function isValidJws(string) {
return JWS_REGEX.test(string) && !!headerFromJWS(string);
}
function jwsVerify(jwsSig, algorithm, secretOrKey) {
if (!algorithm) {
var err = new Error("Missing algorithm parameter for jws.verify");
err.code = "MISSING_ALGORITHM";
throw err;
}
jwsSig = toString(jwsSig);
var signature = signatureFromJWS(jwsSig);
var securedInput = securedInputFromJWS(jwsSig);
var algo = jwa(algorithm);
return algo.verify(securedInput, signature, secretOrKey);
}
function jwsDecode(jwsSig, opts) {
opts = opts || {};
jwsSig = toString(jwsSig);
if (!isValidJws(jwsSig))
return null;
var header = headerFromJWS(jwsSig);
if (!header)
return null;
var payload = payloadFromJWS(jwsSig);
if (header.typ === 'JWT' || opts.json)
payload = JSON.parse(payload, opts.encoding);
return {
header: header,
payload: payload,
signature: signatureFromJWS(jwsSig)
};
}
function VerifyStream(opts) {
opts = opts || {};
var secretOrKey = opts.secret;
secretOrKey = secretOrKey == null ? opts.publicKey : secretOrKey;
secretOrKey = secretOrKey == null ? opts.key : secretOrKey;
if (/^hs/i.test(opts.algorithm) === true && secretOrKey == null) {
throw new TypeError('secret must be a string or buffer or a KeyObject')
}
var secretStream = new DataStream(secretOrKey);
this.readable = true;
this.algorithm = opts.algorithm;
this.encoding = opts.encoding;
this.secret = this.publicKey = this.key = secretStream;
this.signature = new DataStream(opts.signature);
this.secret.once('close', function () {
if (!this.signature.writable && this.readable)
this.verify();
}.bind(this));
this.signature.once('close', function () {
if (!this.secret.writable && this.readable)
this.verify();
}.bind(this));
}
util.inherits(VerifyStream, Stream);
VerifyStream.prototype.verify = function verify() {
try {
var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer);
var obj = jwsDecode(this.signature.buffer, this.encoding);
this.emit('done', valid, obj);
this.emit('data', valid);
this.emit('end');
this.readable = false;
return valid;
} catch (e) {
this.readable = false;
this.emit('error', e);
this.emit('close');
}
};
VerifyStream.decode = jwsDecode;
VerifyStream.isValid = isValidJws;
VerifyStream.verify = jwsVerify;
module.exports = VerifyStream;