Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ before making a package-level licence statement.
[![Latest release](https://img.shields.io/github/v/release/Posnic/POS?include_prereleases&label=latest&color=blue)](https://github.com/Posnic/POS/releases/latest)
[![Tests](https://img.shields.io/badge/tests-9%2C000%2B%20passing-brightgreen)](docs/DEVELOPMENT.md#running-the-tests)
[![Coverage](https://img.shields.io/badge/coverage-69%25%20statements-yellow)](docs/DEVELOPMENT.md#running-the-tests)
[![API](https://img.shields.io/badge/REST%20API-894%20endpoints-blue)](docs/API.md)
[![API](https://img.shields.io/badge/REST%20API-895%20endpoints-blue)](docs/API.md)
[![Source licence](https://img.shields.io/badge/source%20licence-AGPL--3.0-blue)](LICENSE)
[![Package notices](https://img.shields.io/badge/package%20notices-component%20licences-informational)](THIRD-PARTY-NOTICES.md)
[![Platforms](https://img.shields.io/badge/platforms-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey)](https://github.com/Posnic/POS/releases/latest)
Expand Down Expand Up @@ -235,7 +235,7 @@ the free edition worse. This is written down in [GOVERNANCE.md](docs/GOVERNANCE.
| [Contributor quickstart](docs/CONTRIBUTOR_QUICKSTART.md) | Local setup, test commands, issue map, PR flow and safety rules |
| [Developer guide](docs/DEVELOPMENT.md) | Setup, tests, conventions, good first issues |
| [Architecture](docs/ARCHITECTURE.md) | How it fits together, and the parts that bite |
| [REST API](docs/API.md) | 894 endpoints, generated from the routes |
| [REST API](docs/API.md) | 895 endpoints, generated from the routes |
| [Hardware](docs/HARDWARE_MATRIX.md) | Printers, scanners, drawers, scales — and how far each claim is checked |
| [India e-invoicing](docs/INDIA_EINVOICING_DESIGN.md) | Research, readiness inventory and design for GST e-invoicing as an optional feature; no live IRP submission is built |
| [India GST return gaps](docs/INDIA_GST_RETURNS_GAPS.md) | What the GST reports compute today, measured against GSTR-1, 3B and 9 |
Expand Down
23 changes: 23 additions & 0 deletions api/src/routes/mobile-pos.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,29 @@ const limiter = rateLimit({
legacyHeaders: false,
});

// Discovery exposes only public display names, never branch/staff identifiers.
router.get(
'/discovery',
rateLimit({ windowMs: 60000, limit: 60 }),
wrap(async (req) => {
const rows = await req.db
.collection('branches')
.find(
{ module_mobile_pos_enable: { $nin: [false, 0, '0', 'false'] } },
{ projection: { _id: 0, branch_name: 1 } }
)
.limit(10)
.toArray();
return {
shopName: [
...new Set(rows.map((row) => String(row.branch_name || '').trim()).filter(Boolean)),
]
.join(' · ')
.slice(0, 160),
};
})
);

router.post(
'/enrolment-proof',
rateLimit({ windowMs: 60000, limit: 120, standardHeaders: true, legacyHeaders: false }),
Expand Down
4 changes: 3 additions & 1 deletion api/tests/api/rest-smoke.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ describeIfDb('the REST API, against a real database', () => {
* branch would not save. It cannot be caught with a mock: the constraint
* lives in MongoDB, not in the code.
*/
const customers = client.db(DB_NAME).collection('customers');
// Keep this deliberate legacy-index fixture separate from startup migrations,
// which normalize blank emails in the real customers collection asynchronously.
const customers = client.db(DB_NAME).collection('customers_legacy_index_fixture');
await customers.createIndex({ email: 1 }, { unique: true, sparse: true });

await customers.insertOne({ name: 'First', phone: '' });
Expand Down
6 changes: 6 additions & 0 deletions api/tests/mobile-pos.integration.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1304,3 +1304,9 @@ test('mobile snapshot sync carries disabled methods and still accepts a previous
await db.collection('branches').replaceOne({ _id: branch._id }, savedBranch);
}
});

test('public mobile discovery exposes a shop name without credentials or internal identifiers', async () => {
const result = await call('/mobile/v1/discovery', undefined, null);
assert.equal(result.status, 200);
assert.deepEqual(result.data, { shopName: branch.branch_name });
});
7 changes: 4 additions & 3 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Generated from `api/src/routes/` by `npm run docs:api`. Do not edit this file
by hand; edit the routes and regenerate.

**894 endpoints across 53 route groups.**
**895 endpoints across 53 route groups.**

All paths below are relative to the API root. On a desktop install the API runs
on a port derived per installation (see `local-ports.js`); in the cloud it sits
Expand All @@ -15,8 +15,8 @@ behind the tenant hostname.
Postman, Insomnia or Bruno, point Swagger UI or Redoc at it, or generate a
client from it. It is OpenAPI 3.0.3.

**104 of 894 endpoints carry a request schema** (12%), recovered from
their `express-validator` middleware. The remaining 790 are listed with
**104 of 895 endpoints carry a request schema** (12%), recovered from
their `express-validator` middleware. The remaining 791 are listed with
path, method and handler but no body, because inventing a schema is worse than
admitting the gap.

Expand Down Expand Up @@ -730,6 +730,7 @@ Mounted at `/mobile/v1`. Source: `api/src/routes/mobile-pos.routes.js`.

| Method | Path | Body documented | Handler |
|---|---|---|---|
| GET | `/mobile/v1/discovery` | — | `Boolean` |
| POST | `/mobile/v1/enrolment-proof` | — | `hex` |
| POST | `/mobile/v1/pair` | — | `handsetLifetimeSeconds` |
| GET | `/mobile/v1/inventory/policy` | — | `inventory.policy` |
Expand Down
23 changes: 23 additions & 0 deletions docs/openapi.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions tests/public-routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ const ALLOWED_ANONYMOUS = {
'/discovery',
],
'mobile-pos.routes.js': [
// Rate-limited discovery exposes only bounded public shop display names.
// No identifiers, credentials or business data; pairing still proves access.
'/discovery',
// Pairing is a rate-limited authentication entry point with an expiring,
// one-use secret; cloud grants also require the approved phone and proof.
// Discovery proof returns only a nonce MAC for an unexpired random grant,
Expand Down
Loading