# Features — lambda_grinder

Evidence date: 2026-10-10.

Source: `main` at `ffa0b1e0` (2025-03-22).

"Current" means the code is on that revision and is wired from `app.js`, `grinder.js`, `schedule.js`, or `template.yaml`. Draft files that are not the SAM handler are listed separately. Planned items are only those the README or comments describe and the template does not deploy.

Mount paths are relative to the Express app unless the row says API Gateway.

## Current — Lambda breakout

| Feature | Evidence | Status |
|---|---|---|
| URL-encoded fix enqueue | `FixInsert/index.js`, `POST /device/fix/{device_id}` | **Implemented** in SAM. No device check, no authorizer |
| SQS fix queue and DLQ | `template.yaml` `FixProcessingQueue`, `high-volume-dlq`, 14-day retention, 5 receives | **Implemented** in the template |
| Batch grind | `grind/index.js` on that queue, batch 10, window 5 seconds | **Implemented**. Course literal `Steenberg`. Deletes all rounds past 100 locations |
| Layers | `NodeModulesLayer`, `DatabaseLayer`, `LayerAWSSDKONLY` | **Implemented**. `layer1` and `layer2` are commented out |
| X-Ray | `Globals.Function.Tracing: Active`, API `TracingEnabled: true`, `FixInsert` wraps the AWS SDK | **Implemented** in the template |
| API 5xx alarm | `ApiErrorAlarm`, threshold 10 in 60 seconds | **Implemented** in the template. No alarm action is set |
| Deploy profiles | `samconfig.toml` | Test stack names in `us-east-2`, profile `tagm`, `confirm_changeset = true`, `disable_rollback = true` on the default profile |

## Current — API shell

| Feature | Evidence | Notes |
|---|---|---|
| Express JSON API | `app.js` | `body-parser` JSON. Listen on `PORT` |
| CORS allow-list | `app.js` | `ALLOWED_ORIGINS` comma-separated |
| Socket.IO tee-time events | `handlers/teetimes.js` | `teetimes:assignPlayer`, `teetimes:assignTag`. Broadcast payload is `{}` |
| Config field rename on boot | `app.js` | Copies `northEastLatitute` to `northEastLatitude` once |
| JWT gate | `middleware/auth.js` | Header from `TOKEN_HEADER_KEY`, else `Bearer`, else `authorization` |
| Server IP gate | `middleware/server.js` | `SERVER_IP` or `ENV=local` |
| Device IMEI gate | `middleware/twoway.js` | Header `DeviceIMEI` |

## Current — course, devices, rounds

| Feature | Evidence | Auth on the mount |
|---|---|---|
| Import course from `{course}.tagmarshal.com` | `GET /course/change/:course/:importAll?` | None |
| Course setup, map, flags, sections, layout | `routes/course.js` | None |
| Support ticket stored in `ContactSupport` | `POST /course/createSupportTicket` | None. Monday.com call is after `return` |
| Insert one fix, a batch, or a cached batch | `routes/device.js` | None, except tracker reads |
| Device list, assignment, buzzer, actions, management | `routes/device.js` | None on those routes |
| Delete devices | `DELETE /device/devices` | Server IP or `ENV=local` |
| Polling round builder | `grinder.js` | Process, not HTTP |
| Dashboard live map, widgets, round control, marshal notes | `routes/dashboard.js` | JWT |
| Round report and CSV | `routes/modules/roundreport.js` | JWT |
| Round replay | `POST /rounds` | JWT |
| Rerun rounds | `POST /rerun` | JWT |
| Fixes by date | `POST /fixes` | JWT |
| Timing schedule | `routes/modules/timingschedule.js` | JWT |
| Shotgun starts | `routes/modules/shotgun.js` | JWT |
| Hole-time templates and tournaments | `routes/modules/holetimes.js` | JWT |
| Goal times and daily or weekly goal settings | `routes/modules/goaltime.js`, `goalsetting.js` | JWT |
| Analytics hub | `routes/modules/analytics.js` | JWT |

`grinder.js` still contains the round rules the README attributes to a separate Handle Fix function: next section, skipped stop, shotgun, pace, gap, and completion.

## Current — people, tee times, on-course services

| Feature | Evidence | Auth |
|---|---|---|
| Token issue, verify, refresh | `routes/token.js` | Server IP or `ENV=local`. Verify also runs JWT |
| Users, permissions, notification settings | `routes/modules/user.js` | JWT. Writes also call `LOCALHOST` |
| Associate a user | `POST /user-server/postUserToAssociates` | Server IP or `ENV=local` |
| Tee times, tags, CSV upload, provider setup, data directory | `routes/modules/teetime.js` | JWT |
| Tee-sheet sync every 5 minutes | `schedule.js` plus `teetimes/providers/` | Cron, when a provider is configured |
| Default tee times just after midnight | `schedule.js` `10 0 * * *` | Cron, when `defaultTeetimes` is set and today has no sheet |
| Pin templates and schedules | `routes/modules/pinlocations.js` | JWT. Cron applies today's template at `5 0 * * *` |
| Caddie tag API | `routes/caddietag.js` | Mixed. Add, config, fixes, and invites use JWT. `DELETE /caddietag/delete/:email` uses the server gate |
| Caddie reports | `routes/modules/caddie.js` | JWT |
| Players, CSV upload, experience tracker, player fix insert | `routes/modules/player.js` | JWT |
| Player reports | `routes/modules/playerreport.js` | JWT |
| Two-way device API | `routes/modules/twoway.js` | `DeviceIMEI` |
| Food and beverage catalogue, modifiers, kitchen hours, orders | `routes/modules/foodandbev.js` | JWT |
| Geofences, groups, presets, breaches | `routes/modules/geofence.js` | JWT |
| Advertisements | `routes/modules/advertisement.js` | JWT |
| Data directory template | `routes/modules/datadirectory.js` | JWT |
| Marshal notes (interactions) | `routes/modules/interaction.js` | JWT |
| Messaging to devices | `routes/modules/messaging.js` | JWT |
| User notifications | `routes/modules/usernotification.js` | JWT |
| Golf Genius events, rounds, leaderboards | `routes/modules/golfgenius.js` | JWT. Cron also pulls events at midnight when an API key is set |
| Track map, share round, mark incomplete | `routes/modules/trackmap.js` | JWT |

Provider modules that export `processTeetimes`: `clubcaddie`, `clubessential`, `clubmaster`, `clubprophets`, `dgs`, `etx`, `ezlinks`, `foretees`, `foreup`, `gggolf`, `goClub`, `golfgenius`, `golfmanager`, `golfspain`, `jonas`, `jonas-legacy`, `lightspeed`, `membersfirst`, `membersport`, `northstar`, `teeOn`, `teecontrol`, `totalunity`, `whoosh`.

`gggolf.js` posts to `https://golflechampetre.tagmarshal.com/teetimes/providers/gggolf.php`. That host is a literal in the file.

## Current — scheduled maintenance

| Feature | Evidence |
|---|---|
| Legacy fix pull when `legacyBaseUrl` is set | `schedule.js`, every 5 seconds |
| Midnight round close with reason `Closed at midnight` | `schedule.js` |
| Temporary device assignment flipped in the midnight job | `schedule.js`. The `marshal: false` argument is passed as Mongoose options |
| ETX tournament refresh at midnight | `modules/europeanTour.js` when provider is `etx` |

## Drafts and unwired files

These files are in git. They are not `Handler: index.handler` and they are not mounted from `app.js`.

| Path | What it is |
|---|---|
| `grind/index copy.js` | Longer handler using the MongoDB driver and `/opt/modules` |
| `grind/newgrind.js` | Handler with schemas inlined, exports `handler` |
| `grind/grind-new.js` | Another grind draft |
| `grind/GrinderFunction.js.txt`, `grind/inserFixFunction.js.txt`, `grind/template_yaml.txt` | Notes, not running code |
| `layers/layer1/` | Full copy of models and modules. Commented out of `template.yaml` |
| `testdb/` | Commented `TestDb` function in the template. The comment gives it `AmazonDynamoDBFullAccess` and the same style of Mongo URL |
| `.aws-sam/build/` | Committed `sam build` output, including copies of the grind drafts |
| `modules/rounds copy.txt` | Text copy beside `modules/rounds.js` |

## Planned or described but not deployed

| Item | Evidence | Status |
|---|---|---|
| Scheduled Grind every 5 minutes | `README.md` | **Documented**. No `Schedule` event in `template.yaml` |
| Handle Fix Lambda | `README.md`. Commented output `HandleFixFunctionARN` | **Not in Resources** |
| Get Raw Fixes Lambda, `POST /getRawFixes` | `README.md`. Commented output `GetRawFixesFunctionARN` | **Not in Resources**. The polling function `getRawFixes` remains inside `grinder.js` |
| `layer2` | Comment in `template.yaml` | No `layers/layer2` directory was in the git file list |
| FIFO queue | Commented `FifoQueue` on `FixQueue` | Not active |

## Removed or not in this revision

The onboarding snapshot (2026-09-28) listed `sonar-project.properties` and `sonarqube_scan.bat` on the scan host. They are not in `main` at `ffa0b1e0`.

`controllers/ngrinder.js` is not in this tree. The polling processor is `grinder.js`.

## Recently changed

`ffa0b1e0` (2025-03-22, "update files for deployment") adds `.aws-sam/build/**` and updates packaged layer dependencies. The commit is large because `node_modules` under the AWS SDK layer is tracked.

`737d492b` (2025-03-19) is subject "before tear down". What was torn down is **Unknown**. The following commit is the build-output update above.

`bd67ccef` and `4e9a04b0` (2025-03-07) are "adding new layers".

## Deprecated

No feature is marked deprecated in code. The boot comment on the latitude field rename says "remove at later stage". The special-device skip in `grinder.js` says "TODO:: Remove special devices".
