Skip to content

[Feature]: Allow administrators to dismiss unknown inbound registration requests #7

Description

@awatchar

Component

Configuration portal

Problem to solve

The Device registry displays unregistered Device IDs under:

INBOUND REQUESTS → Awaiting registration

An inbound request may appear even when the administrator did not initiate provisioning and does not recognize the Device ID.

For example, an unknown request for Device ID AB12C3 appeared in the portal. The current interface provides only a Register action. There is no way to dismiss, reject, or remove an unknown request.

The administrator should not be forced to register an unknown device or wait up to 24 hours for the pending entry to expire automatically.

Current behavior

The pending-registration interface currently provides only:

  • Device ID
  • Request count
  • Last request time
  • Register button

The storage layer already provides:

deletePendingDeviceRequest(deviceId)

However, the pending-device API currently implements only GET, and the Admin Portal does not expose a dismiss action.

Deleting a registered device is supported elsewhere in the portal, but that operation must remain completely separate from dismissing a pending registration request.

Desired outcome

Add a Dismiss or Ignore action to each entry under Awaiting registration.

When an administrator dismisses a pending request:

  1. Display a confirmation dialog containing the Device ID.
  2. Clearly explain that only the pending request will be removed.
  3. Do not create or register a Device Profile.
  4. Do not delete or modify any registered device.
  5. Remove the pending request from Cloudflare KV.
  6. Remove the row from the interface after the API confirms success.
  7. Display a success notification.
  8. Prevent the same unknown Device ID from immediately reappearing if it continues sending requests.

Example confirmation text:

Dismiss registration request from AB12C3?

This removes only the pending request. It will not register the device or modify any existing Device Profile.

Proposed API

Add an authenticated mutation endpoint such as:

DELETE /api/devices/pending/AB12C3

The endpoint should:

  • Require an authenticated administrator session.
  • Use the existing admin-mutation security checks.
  • Enforce same-origin validation.
  • Enforce browser/human verification where required.
  • Validate the Device ID using the existing validDeviceId() function.
  • Delete only the corresponding pending-device:<deviceId> entry.
  • Never delete a device:<deviceId> record.
  • Return an idempotent successful response if the pending entry has already disappeared.
  • Return a safe error message when the request store is unavailable.
  • Never disclose Cloudflare credentials, KV metadata, or private configuration.

Example successful response:

{
  "ok": true,
  "deviceId": "AB12C3"
}

Reappearance and suppression behavior

Deleting only the current KV entry may not be sufficient because an unknown client can immediately send another configuration request and recreate the pending entry.

Dismissed Device IDs should therefore be temporarily suppressed.

Suggested behavior:

  • Store a dismissal marker separately from the pending request.
  • Suppress the dismissed Device ID for at least the existing 24-hour inbound-request window.
  • Do not increase the request count or recreate the visible pending entry during that period.
  • Do not return any registered-device configuration to a dismissed Device ID.
  • Continue returning the normal generic 404 Not found response.
  • Avoid exposing whether the Device ID was dismissed, unknown, or registered.
  • Allow the request to become visible again after the suppression period expires.
  • Registering the Device ID intentionally should clear any dismissal marker.

Suggested KV structure:

pending-device:AB12C3
dismissed-pending-device:AB12C3

The dismissal marker should have a TTL and must not contain credentials, tokens, configuration, IP addresses, or unnecessary client information.

User interface

Each pending request row should include two clearly separated actions:

  • Register
  • Dismiss

The Dismiss action should:

  • Use a secondary or danger visual style.
  • Include an accessible label containing the Device ID.
  • Require confirmation before sending the request.
  • Disable repeated clicks while the request is in progress.
  • Remove the row only after the server confirms success.
  • Preserve the row and display an error notice if the operation fails.
  • Update the Awaiting registration count immediately after success.
  • Hide the complete inbound-request section when no pending requests remain.

The action must remain visually distinct from deleting a registered Device Profile.

Acceptance criteria

  • Every pending registration row has a Dismiss or Ignore action.
  • Selecting the action displays a confirmation containing the Device ID.
  • Cancelling the confirmation makes no changes.
  • Confirming calls an authenticated pending-request deletion endpoint.
  • The endpoint validates the Device ID.
  • The endpoint uses the existing admin-mutation security controls.
  • Only the matching pending request is removed.
  • No registered Device Profile is deleted or modified.
  • The dismissed row disappears only after a successful API response.
  • The pending-request count updates immediately.
  • The inbound-request section disappears when the final row is dismissed.
  • A success notification identifies the dismissed Device ID.
  • An API or KV failure leaves the row visible and displays an actionable error.
  • Repeated dismissal requests are safe and idempotent.
  • A continuously requesting unknown Device ID does not immediately reappear.
  • Dismissal expires automatically after the defined suppression period.
  • Intentionally registering the Device ID clears its pending and dismissal records.
  • Dismissed and unknown devices continue receiving the same generic 404 response.
  • Automated tests cover authorization, validation, deletion, suppression, expiry, and registered-device isolation.
  • Existing Register behavior continues to work.

Test cases

Dismiss an unknown request

  1. Request configuration for an unregistered Device ID.
  2. Confirm that it appears under Awaiting registration.
  3. Select Dismiss.
  4. Confirm the action.
  5. Verify that the row and its pending KV record are removed.
  6. Verify that no Device Profile was created.

Cancel dismissal

  1. Select Dismiss for a pending request.
  2. Cancel the confirmation.
  3. Verify that the row and KV record remain unchanged.

Protect registered devices

  1. Create a registered Device Profile.
  2. Create or simulate a pending entry with the same Device ID.
  3. Dismiss the pending entry.
  4. Verify that the registered Device Profile and configuration remain intact.

Prevent immediate reappearance

  1. Dismiss an unknown Device ID.
  2. Continue requesting its configuration endpoint.
  3. Verify that the API continues returning the generic 404 response.
  4. Verify that the Device ID does not immediately return to the pending list.
  5. Verify that it can appear again only after the dismissal TTL expires.

Register after dismissal

  1. Dismiss a pending Device ID.
  2. Intentionally create a Device Profile for the same Device ID.
  3. Verify that the dismissal marker is removed.
  4. Verify that the device can retrieve its configuration normally.

Constraints and safety considerations

  • Dismissing a request must never be equivalent to deleting a registered device.
  • Do not automatically register unknown Device IDs.
  • Do not reveal configuration or registration state through different public error responses.
  • Do not store source IP addresses, device tokens, credentials, or private request data in dismissal records.
  • Do not provide an unauthenticated bulk-delete endpoint.
  • A future bulk-clear action, if added, should require separate confirmation and should not be part of this initial change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions