# Known Issues & Deployment Notes

## Issue #1: Wrong Pushy API Key (CRITICAL)

**Status**: ✅ Fixed — fallback key updated in code  
**Impact**: Terminal never receives transaction notifications → payments timeout  
**Root Cause**: Hardcoded fallback key in `CardmachineController.php` → `sendPushIfPossible()`  

### Details

The hardcoded fallback Pushy API key was the old key `4e73c...`. Updated to the correct new key `b312c...` as the default fallback.

### What was changed

1. Updated the fallback key in `sendPushIfPossible()` from old `4e73c...` to new `b312c...`
2. Added `CARDMACHINE_PUSHY_API_KEY` to `.env.example`

### Production deployment

For extra safety, also add the key explicitly to production `.env`:
```
CARDMACHINE_PUSHY_API_KEY=b312c020235947fd0aae0ef6cbc73b79fcde2da0f3ddbbc2aae1931ae5f0181e
```
Then run `php artisan config:clear`.

---

## Issue #2: Missing Terminal Management Routes

**Status**: ✅ Fixed — all routes implemented in `CardmachineController`  
**Impact**: Was returning `status: 107` for terminal management calls  

### Details

The following routes were added to the `match ($route)` block:

| Route | Method | Description |
|---|---|---|
| `get_terminals` | `getTerminals()` | List all terminals for the authenticated account |
| `register_terminal` / `create_terminal` | `registerTerminal()` | Create a new terminal with messaging_id |
| `update_terminal` | `updateTerminal()` | Update terminal messaging_id and other fields |
| `send_verify_terminal` | `sendVerifyTerminal()` | Send verification push to terminal |

### Implementation Notes

- All new routes use `resolveAccountId()` for token validation (consistent with existing routes)
- `get_terminals` returns the format expected by `TerminalsActivity.java`: array of `{terminal_id, terminal_name, advertisement_url, pin_required}`
- `pin_required` defaults to `"0"` since the column doesn't exist in the migration (matches legacy behavior)
- `register_terminal` accepts params from `NewTerminal.java`: `{terminal, name, messaging_id, advertisement_url}`
- `update_terminal` accepts params from `VerifyingActivity.java`: `{terminal, messaging_id}`
- `send_verify_terminal` sends Pushy push with `{secret: VERIFICATION_SECRET}` matching `PushReceiver.java`
- Verification secret is configurable via `CARDMACHINE_VERIFICATION_SECRET` env var

---

## Incident: Transaction Push Delivered But Terminal Never Updates

**Status**: ✅ Root cause identified and fixed on both sides

### Symptoms observed

- `initiate_transaction` returns success and transaction ID
- `cardmachine.push.response` shows Pushy success with `devices: 1`
- Kiosk keeps polling `get_status_flow` and receives `[]`
- Terminal sends `update_transaction_status` and `update_status_flow` with `id: 0`
- Callback requests return `402` due to expired token

### Root causes

1. Terminal app read `transaction_id` incorrectly when payload type was non-string.
2. Ghost callback from third-party PAX apps could trigger result handling with `transactionId = 0`.
3. Terminal outcome updates reused stale tokens.

### Terminal app fixes (v2.2.1)

- `PushReceiver.java`: robust parsing helper for String/Integer/Long (`getStringOrInt`) and extra payload logging
- `PosBridgeActivity.java`: guard against ghost `id: 0` outcome processing
- `PosBridgeActivity.java`: always refresh token before outcome updates; clear transaction id after processing

### Backend compatibility fix

- In `CardmachineController::initiateTransaction()`, push payload now casts values to string:
	- `transaction_id` => `(string) $transactionId`
	- `amount` => `(string) $amount`

### Live diagnostics

- Viewer: `https://icard.orderbuddy.tech/cardmachine/logs`
- API: `https://icard.orderbuddy.tech/cardmachine/logs/api?date=YYYY-MM-DD&lines=200&filter=push`

---

## Issue #3: Kiosk Polling Forever / Terminal Hardware Errors Not Surfaced

**Status**: ✅ Fixed across backend, terminal app, and kiosk client

### Symptoms observed

- Terminal-side failures like "Printer Out Of Paper" occurred.
- Kiosk kept polling `get_status_flow` and never exited the payment screen.
- In failing cases, kiosk often received fallback values such as `["completed"]`.

### Root causes

1. `get_status_flow` fallback used raw status values (`completed`, `failed`) that kiosk logic did not always treat as terminal states.
2. Some terminal failure paths had empty `status_flow`, so kiosk had less context.
3. Kiosk polling timeout was configured but not enforced, which allowed effectively infinite polling.
4. Transient network errors in polling path could terminate flow too aggressively.

### Backend fix

- `CardmachineController::getStatusFlow()` fallback now returns kiosk-recognizable terminal strings:
	- Approved -> `Transaction Approved`
	- Failed/Declined -> `Transaction Declined`
	- Cancelled -> `Transaction Cancelled`
- Intermediate states (`new`, `received`, `processing`, `completed`) now return empty fallback flow so kiosk can continue polling until a definitive state is available.

### Terminal app hardening

- `PosBridgeActivity::sendTransactionOutcomeUpdates()` now always sends `update_status_flow`.
- When SDK status events are empty, it injects synthetic flow values:
	- `Transaction Approved`
	- `Transaction Declined`
	- `Transaction Cancelled`

### Kiosk flow hardening

- Enforced polling timeout (`MAX_REQUEST_COUNT`) to avoid infinite wait screens.
- Added retry budget for transient polling/token errors before showing a connection failure.
- Improved error detection for hardware and generic error strings (including out-of-paper conditions).
- Improved customer-facing status messages during waiting/processing phases.
- All terminal failure states now resolve to clear UX actions (retry or back-to-cart), preventing dead-end flows.

---

## Environment Checklist for Production (Updated 2026-06-15)

| Variable | Required | Purpose |
|---|---|---|
| `CARDMACHINE_PUSHY_API_KEY` | **YES** | Terminal push notification delivery |
| `CARDMACHINE_TOKEN_SECRET` | Optional | JWT HMAC key (has fallback) |
| `CARDMACHINE_API_SECRET` | Optional | Login shared secret (has fallback) |
| `FIREBASE_PROJECT_ID` | **YES** | FCM V1 API project targeting |
| `FIREBASE_WEB_API_KEY` | **YES** | Firebase Identity Toolkit token validation |
| `FIREBASE_SERVICE_ACCOUNT_PATH` | **YES** | FCM V1 OAuth2 authentication (service account JSON) |
| `FIREBASE_IOS_BUNDLE_ID` | Optional | APNs topic header (defaults to com.CutPay.FriezAndBurgz) |
| `MOBILE_PORTAL_DEFAULT_STORE` | Optional | Default store_app_id for mobile API |
| `DB_*` | YES | Database connection |

---

## Deployment Commands

```bash
# After .env changes
php artisan config:clear
php artisan cache:clear

# After code changes
php artisan optimize

# After view/blade changes
php artisan view:clear

# Run migrations (new tables)
php artisan migrate --force
```
