Skip to content

[render preview]test5#3

Merged
dadachi merged 1 commit into
mainfrom
test5
Oct 26, 2024
Merged

[render preview]test5#3
dadachi merged 1 commit into
mainfrom
test5

Conversation

@dadachi
Copy link
Copy Markdown
Contributor

@dadachi dadachi commented Oct 26, 2024

No description provided.

@dadachi dadachi deployed to test5 - nativeapptemplateapi PR #3 October 26, 2024 06:16 — with Render Active
@dadachi dadachi temporarily deployed to test5 - sidekiq-worker PR #3 October 26, 2024 06:17 — with Render Destroyed
@dadachi dadachi temporarily deployed to test5 - nativeapptemplateapi PR #3 October 26, 2024 06:17 — with Render Destroyed
@dadachi dadachi merged commit 30d326c into main Oct 26, 2024
@dadachi dadachi deleted the test5 branch October 26, 2024 06:42
dadachi added a commit that referenced this pull request May 10, 2026
Layer 1 of the agent's reviewer (per the agent's docs/SPEC.md)
checks OpenAPI parity between Rails ↔ iOS networking ↔ Android
repository layers. Adding the Device controller without the
corresponding spec entries means PRs #3-5 (the iOS/Android push
registration clients) wouldn't have a contract to integrate against
and would fail Layer 1 contract-parity scan.

Adds:
- Tag: Devices
- Path POST /devices: idempotent register; 201 on create, 200 on
  touch, 422 on validation error
- Path DELETE /devices/{deviceId}: 204 no_content, 404 if device
  isn't owned by current_shopkeeper
- Schemas: DeviceAttributes, Device, DeviceCreateRequest
  (jsonapi-style envelope to match the rest of the API)

YAML parses; paths now 25, schemas now 38.
dadachi added a commit that referenced this pull request May 10, 2026
* Add push notifications scaffolding via noticed v2

PR #1 of 5 in #58. Scaffolds the Rails-side groundwork for native push
notifications. Provider integration (APNs + FCM) and ItemTag AASM
wiring follow in PR #2 once APNs .p8 and FCM service-account JSON are
provisioned. Client work (free + paid iOS/Android) follows in PRs #3-5.

What lands here
- noticed v2 gem + the two engine migrations (Noticed::Event,
  Noticed::Notification, both UUID-keyed to match this substrate's
  primary_key_type)
- Device model + migration: shopkeeper-scoped, unique on
  [platform, token], last_active_at for staleness scoping; ios/android
  enum
- Api::V1::Shopkeeper::DevicesController:
    POST /api/v1/shopkeeper/devices  — idempotent upsert (rebinds token
                                       to current_shopkeeper if it
                                       previously belonged to someone
                                       else, e.g. shared device after
                                       sign-out/sign-in); 201 on
                                       create, 200 on touch
    DELETE /api/v1/shopkeeper/devices/:id — unregister (404 on someone
                                            else's device, scoped via
                                            current_shopkeeper.devices)
- DevicePolicy + DeviceSerializer following existing substrate
  conventions (BasePolicy + JSONAPI::Serializer)
- ApplicationNotifier base + example ItemTagCalledNotifier (no
  delivery methods wired yet — title/body/url are i18n-resolved via
  notification_methods so PR #2 just needs to add deliver_by :ios +
  :android and trigger from ItemTag's AASM complete event)
- Shopkeeper.has_many :devices (dependent: :destroy) and
  :notifications (as: :recipient, class: Noticed::Notification)
- Locale entries under notifiers.item_tag_called

Tests: 21 new runs (Device model 9, DevicesController 8, notifier 4),
0 failures. Full suite now 419 runs / 868 assertions / 0 failures /
0 errors / 0 skips. rubocop clean (239 files, 0 offenses).

* Wire deliver_by :action_push_native via Rails-native action_push_native

Install action_push_native 0.3.x and generate ApplicationPushNotification,
ApplicationPushDevice, ApplicationPushNotificationJob, and config/push.yml.
Add deliver_by :action_push_native to ItemTagCalledNotifier so push
notifications route through Rails 8.1's Action Push Native (single
abstraction over APNs + FCM) instead of the Noticed gem's per-platform
:ios / :fcm deliverers.

APNs/FCM credentials remain placeholders in config/push.yml — provision
via bin/rails credentials:edit before enabling delivery. Bridging the
existing Device registration API to ApplicationPushDevice (so registered
tokens actually flow into Action Push Native delivery) is a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Generalize notifier copy: %{number} → %{name}, drop "Number" prefix

Substrate post-Phase-1 (#45) is generic single-resource CRUD, not
queue-only — `ItemTag.name` can be a queue number ("A001"), a pet
name ("Mittens"), a task title, etc. The copy "Number %{number} is
up" only reads correctly for the queue case, and the agent's renamer
doesn't substitute the word "Number" (it's not in the rename plan),
so the wrong copy ships to every renamed app.

Change to "%{name} is ready" — generalizes cleanly across the queue,
reservation, vet-clinic, and task-tracker domains the substrate
targets. Body unchanged.

Test passes; rubocop clean.

* Generalize notifier: drop "Called" + state-verb copy (rename-resistant)

Reverses the previous "Number → name" / "is ready" decision once it
became clear that any state-verb baked into the substrate's notifier
title or class name fights the agent's domain-adapt step. The agent
extends/renames the AASM state machine per spec (idled/completed →
e.g. waiting/seated for restaurant, pending/seen for vet clinic), but
its rename plan only handles the four model-level tokens (Shop /
Shopkeeper / ItemTag / NativeAppTemplate). State names cascading into
notifier file/class/locale-key/title are out of scope for the
rename-safety contract (#57).

So the substrate's notifier ships state-verb-free:

- File:        item_tag_called_notifier.rb → item_tag_notifier.rb
- Class:       ItemTagCalledNotifier       → ItemTagNotifier
- Locale key:  notifiers.item_tag_called   → notifiers.item_tag
- Title:       "%{name} is ready"          → "%{name}"
- Body:        "Please proceed to %{shop}." → "%{shop}"

`ItemTag` itself IS in the rename plan, so file/class/locale-key
cascade through `item_tag → patient/reservation/todo` cleanly.
`%{name}` and `%{shop}` are interpolation keys, not renameable
tokens. Result: substrate copy survives any state-verb rewrite the
agent's adapt step does, at the cost of vague substrate copy. The
adapt step can rewrite richer per-domain copy when it wants.

Tests + rubocop clean.

* Swap notifier title/body: shop in title, item name in body

Push-notification UX convention is source-in-title, event-in-body —
WhatsApp (sender → message), Slack (channel → message), Calendar
(event → location). Shop is the recognizable persistent entity that
anchors the notification; item name is variable per-event content.

Title: %{name} → %{shop}
Body:  %{shop} → %{name}

Tests + rubocop clean.

* credentials.yml.tt: add action_push_native APNs + FCM placeholders

config/push.yml looks up Rails.application.credentials.dig(
:action_push_native, :apns, :key_id) and friends, but the credentials
template that seeds `bin/rails credentials:edit` on first generation
didn't expose those keys. Fresh developers would hit silent nil on
first push delivery without knowing where the lookup expected the
secret.

Adds the same shape Resend's api_key already follows: empty
placeholder under the documented key path. Comment notes which
inputs are needed (APNs key_id + .p8 contents, FCM service-account
JSON).

* push.yml: move team_id/topic/project_id to credentials too

Three deployment-specific values were still hard-coded as placeholders
in config/push.yml:

- apple.team_id    (Apple Developer team identifier — per-deployer)
- apple.topic      (iOS bundle identifier — per-deployment)
- google.project_id (Firebase project identifier — per-deployment)

These don't belong in source. apple.topic in particular is a rename-
pipeline trap: the agent renames the iOS bundle id when generating a
domain-customized variant (com.nativeapptemplate.* → com.<spec>.*),
but the rename pipeline only operates on code/locales/OpenAPI — not
on push.yml strings. So a hard-coded `your.bundle.identifier` here
silently desyncs from the renamed app's actual bundle id and push
delivery breaks with a non-obvious error.

Move all three to Rails.application.credentials.dig(:action_push_native,
...) so they're deploy-time configuration, not source-controlled
state. Add the same fields to the credentials.yml.tt template so
`bin/rails credentials:edit` exposes the expected key paths.

Tests + rubocop clean.

* openapi.yaml: document Device endpoints + schemas

Layer 1 of the agent's reviewer (per the agent's docs/SPEC.md)
checks OpenAPI parity between Rails ↔ iOS networking ↔ Android
repository layers. Adding the Device controller without the
corresponding spec entries means PRs #3-5 (the iOS/Android push
registration clients) wouldn't have a contract to integrate against
and would fail Layer 1 contract-parity scan.

Adds:
- Tag: Devices
- Path POST /devices: idempotent register; 201 on create, 200 on
  touch, 422 on validation error
- Path DELETE /devices/{deviceId}: 204 no_content, 404 if device
  isn't owned by current_shopkeeper
- Schemas: DeviceAttributes, Device, DeviceCreateRequest
  (jsonapi-style envelope to match the rest of the API)

YAML parses; paths now 25, schemas now 38.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dadachi added a commit that referenced this pull request May 10, 2026
Drop the standalone Device model and consolidate push-token
registration onto ApplicationPushDevice (subclass of
ActionPushNative::Device) so deliver_by :action_push_native actually
fires for tokens registered via POST /api/v1/shopkeeper/devices.

- Drop devices table; rebuild action_push_native_devices with UUID
  primary key + UUID polymorphic owner + bundle_id / last_active_at
  columns + unique (platform, token) index
- Move validations / active scope / last_active_at touching from
  Device onto ApplicationPushDevice
- Shopkeeper has_many :application_push_devices, as: :owner
- DevicesController now manages ApplicationPushDevice; JSONAPI type
  stays "device" via set_type :device on the new serializer
- API contract change (pre-mobile-client): device.platform enum is
  now [apple, google] (matches Action Push Native's APNs/FCM
  convention). PRs #3-5 (iOS/Android substrate clients) will
  register with apple or google.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant