# Business rules — formulys_simpleflow_backend

Evidence date: 2026-10-14.

Source: `git@bitbucket.org:overdrive/formulys_simpleflow_backend.git`, `master` at `c30ed2b` (2024-06-05).

No business-rules document exists in the source repository. The rules below are constraints the committed schema, handlers, and configuration actually state. Anything marked **Inferred** is a conclusion from that evidence, not a written policy. Do not treat these as approved product policy without human confirmation.

## Identity and tenancy

### BR-001 — A user must have a username, password, and role

**Implemented** in `models/User.js`.

`username`, `password`, and `role` are each `required: true`. Mongoose would reject a save that omits them. No application route performs that save in this repository.

Evidence: `models/User.js`.

### BR-002 — Usernames are unique

**Implemented.**

`username` has `unique: true`. Duplicate username inserts would fail at the MongoDB unique index once created by Mongoose. Index creation at runtime was not executed in this inspection.

Evidence: `models/User.js`.

### BR-003 — Role is limited to three values

**Implemented.**

```text
enum: ['tenantUser', 'tenantAdmin', 'platformAdmin']
```

Any other string is invalid for `role` at the schema layer. What each role may do is **not** encoded anywhere else in the repository. Provenance of permissions for those roles: **Unknown**.

Evidence: `models/User.js`.

### BR-004 — A user may belong to a tenant

**Implemented** as an optional field.

`tenantId` is an ObjectId with `ref: 'Tenant'`. It is not marked `required`. Whether platform admins must omit it, and whether tenant users must have it, is **Unknown / Requires Confirmation**.

**Inferred:** the product was intended to be multi-tenant because of the field name, the `Tenant` ref, and role names that include `tenant` and `platform`.

Evidence: `models/User.js`. There is no `Tenant` model file.

### BR-005 — Passwords are stored as plain strings in the schema

**Implemented** as schema type only.

`password` is `{ type: String, required: true }`. There is no pre-save hook, bcrypt/argon dependency, or hashing helper in the tree. Whether plaintext storage was intentional is **Unknown / Requires Confirmation**. Treating plaintext as an approved business rule would be unsafe; record it as implemented schema behaviour only.

Evidence: `models/User.js`, `package.json` (no password-hashing package).

## HTTP and realtime behaviour

### BR-006 — The root HTTP path is publicly readable

**Implemented.**

`GET /` has no auth middleware and returns `Hello World`. CORS is not configured in source (Socket.io / Express defaults apply).

Evidence: `server.js`.

### BR-007 — Socket `message` events are broadcast to all connected clients

**Implemented** in both handler locations.

On `socket.on('message', (msg) => { io.emit('message', msg); })` there is no authentication, no room, no tenant filter, and no payload validation. **Inferred:** any connected client can send a payload that every other connected client receives.

Evidence: `server.js`, `socket_handlers/index.js`.

### BR-008 — Socket connect and disconnect are logged, not authorized

**Implemented.**

Connect and disconnect only `console.log`. No session, token, or user binding is applied.

Evidence: `server.js`, `socket_handlers/index.js`.

## Configuration and operations

### BR-009 — MongoDB location comes from `MONGO_URI`

**Implemented.**

The application reads `process.env.MONGO_URI`. A `.env` file defining that key is tracked in git. Operators who clone the repo receive that file unless they replace it. Whether the committed value is a shared, local, or obsolete database is **Unknown / Requires Confirmation**.

Evidence: `server.js`, `.env` (key only documented here).

### BR-010 — Listen port defaults to 3000

**Implemented.**

`const PORT = process.env.PORT || 3000`.

Evidence: `server.js`.

### BR-011 — `.env` is not excluded by `.gitignore`

**Implemented** as absence.

The ignore file does not list `.env`, and `.env` is present in `git ls-files`. **Inferred** operational risk: secrets travel with the repository history.

Evidence: `.gitignore`, `git ls-files`.

## Rules that do not exist in code

The following common product rules were **not** found and must not be assumed:

- Authentication or session rules
- Authorization checks by `role`
- Password complexity or rotation
- Rate limiting
- Input validation beyond Mongoose schema types
- Soft delete, audit fields, or timestamps (`timestamps: true` is not set on the schema)
- Data retention or tenancy isolation on queries

Mark desired policy for those areas **Unknown / Requires Confirmation**.

## Human confirmation needed

1. Confirm whether BR-003 role names are the approved role set for Formulys / Simpleflow.
2. Confirm tenant rules for `tenantId` and a `Tenant` collection.
3. Confirm password hashing and auth requirements (BR-005 is schema behaviour, not an approved security policy).
4. Confirm whether open socket broadcast (BR-007) is acceptable for any environment.
5. Confirm whether `.env` should remain in git history or be rotated and removed from tracking.
