Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
10ffa35
Add substrate v2 overview and phase 1 Rails API checklist
dadachi Apr 23, 2026
b3101af
Clarify ItemTag policy uses Shop permissions (no separate ItemTag perms)
dadachi Apr 23, 2026
e6010a0
Remove NFC scan routes and display namespace
dadachi Apr 23, 2026
4ad1101
Remove display namespace
dadachi Apr 23, 2026
0182387
Remove static controller, scan actions, and root route
dadachi Apr 23, 2026
3b96ef7
Refactor ItemTag schema: rename queue_number, add description/positio…
dadachi Apr 23, 2026
faad0b1
Refactor ItemTag model for generic CRUD
dadachi Apr 23, 2026
cce738f
Simplify Shop model: replace queue auto-generation with single sample…
dadachi Apr 23, 2026
38e9a78
Update ItemTag controller for new schema
dadachi Apr 23, 2026
1309745
Inline complete/idle state transitions, drop tag-named wrapper methods
dadachi Apr 23, 2026
a8dd3b7
Update serializers for new ItemTag schema
dadachi Apr 23, 2026
51bec4c
Update ItemTag policy: 2-tier admin/member, add idle, drop reset
dadachi Apr 23, 2026
c5125e7
Update madmin resource for new ItemTag schema
dadachi Apr 24, 2026
c42249e
Redesign roles (admin/member) and permissions (generic CRUD)
dadachi Apr 24, 2026
93ac5d3
Collapse roles to admin/member tier across model and madmin
dadachi Apr 24, 2026
a969128
Update locales for new ItemTag schema and item-tag UI label
dadachi Apr 24, 2026
a80dd77
Update model tests for refactored schema and 2-tier roles
dadachi Apr 24, 2026
5bd5b6d
Update serializer tests for refactored ItemTag/Shop attributes
dadachi Apr 24, 2026
e358da7
Update policy tests for admin/member roles and idle action
dadachi Apr 24, 2026
4fe3bf9
Update controller tests for refactored API and 2-tier roles
dadachi Apr 24, 2026
27d462a
Fix bin/ci: rubocop trailing blank line and brakeman fingerprint refresh
dadachi Apr 24, 2026
29dd109
Documentation cleanup for substrate v2
dadachi Apr 24, 2026
a739a44
Drop dead queue-length config, controller meta, and test assertion
dadachi Apr 24, 2026
0aee768
Set sample item_tag position to 1
dadachi Apr 24, 2026
b95d20e
Remove orphan click_connectedly/click_repeatedly stimulus controllers
dadachi Apr 24, 2026
3c223c6
Auto-assign ItemTag.position to max+1 on create when not provided
dadachi Apr 24, 2026
83f5699
Broaden ShopPolicy to admin || member per collaborative model
dadachi Apr 24, 2026
c729d0a
Add rake task to backfill item_tags.position for existing rows
dadachi Apr 25, 2026
1f8a900
Merge add_value_to_item_tag_position_rake_task into phase1-rails-api
dadachi Apr 25, 2026
50f2eb4
Document SOLID_QUEUE_IN_PUMA=true in .env.sample for dev
dadachi Apr 26, 2026
164fe67
Remove unused bin/update script
dadachi Apr 27, 2026
c11af4f
Add role_redesign:migrate rake task for legacy role data
dadachi Apr 27, 2026
680e9b6
Remove apple-app-site-association (queue-scan deep link retired)
dadachi Apr 27, 2026
7669b93
Remove Turbo from README features list
dadachi Apr 27, 2026
055d762
Simplify item_tag not_found message
dadachi Apr 27, 2026
9ef6236
Add tests for previously uncovered code paths (#47)
dadachi Apr 29, 2026
fbc8954
Refactor: small cleanups across models and controllers (#48)
dadachi Apr 29, 2026
08c840f
Ignore .claude/scheduled_tasks.lock
dadachi Apr 29, 2026
e5e8d33
Rate-limit shopkeeper sign-up to 10/IP/3min (#50)
dadachi Apr 29, 2026
1399dcb
Fix SessionsController nuking current_platform on header-less sign-in…
dadachi Apr 29, 2026
f6ad1c5
Move login throttles into SessionsController via rate_limit (#51)
dadachi Apr 29, 2026
12e666c
Remove dead code: unused gems and locale keys (#52)
dadachi Apr 29, 2026
8b596ec
Normalize NATEMPLATE_API_DOMAIN docs to NATIVEAPPTEMPLATE_API_DOMAIN …
dadachi May 1, 2026
70eb2b0
Update gems within Gemfile constraints
dadachi May 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
#
# Never use 127.0.0.1, localhost, or 0.0.0.0. When your Wi-Fi IP
# changes, update HOST here and the matching values in the mobile
# apps (Xcode scheme NATEMPLATE_API_DOMAIN and Android
# ~/.gradle/gradle.properties NATEMPLATE_API_DOMAIN).
# apps (Xcode scheme NATIVEAPPTEMPLATE_API_DOMAIN and Android
# ~/.gradle/gradle.properties NATIVEAPPTEMPLATE_API_DOMAIN).

HOST=192.168.1.21
PORT=3000

# Run Solid Queue inside Puma so background jobs (e.g. invitation emails
# via deliver_later) are processed in development. Mirrors production
# (see render.yaml).
SOLID_QUEUE_IN_PUMA=true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
.claude/logs/
.claude/tmp/
.claude/*.log
.claude/scheduled_tasks.lock

# Private docs — not for publication
/docs-private/
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ bin/rails dbconsole # Database console
- `Account` - Top-level tenant/organization
- `Shopkeeper` - Main user type (belongs to Account)
- `Shop` - Core business entity (belongs to Account)
- `ItemTag` - Belongs to Shop with unique name constraint
- `ItemTag` - Belongs to Shop; has name/description/position and a binary state (idled/completed)
- `Role` & `Permission` - Authorization system
- State machines implemented with AASM gem

Expand All @@ -96,7 +96,7 @@ bin/rails dbconsole # Database console
- Run tests: `bin/rails test` (205 tests, 402 assertions)

### Development Server Configuration
- `HOST` (Wi-Fi IP) and `PORT` are required in `.env`; `Procfile.dev` uses `${HOST:?...}` so Rails fails loudly if unset, and `development.rb` uses `ENV.fetch("HOST")` for `action_mailer.default_url_options`. Must match `NATEMPLATE_API_DOMAIN` in the iOS scheme and Android `gradle.properties`. Never `127.0.0.1`, `localhost`, or `0.0.0.0`.
- `HOST` (Wi-Fi IP) and `PORT` are required in `.env`; `Procfile.dev` uses `${HOST:?...}` so Rails fails loudly if unset, and `development.rb` uses `ENV.fetch("HOST")` for `action_mailer.default_url_options`. Must match `NATIVEAPPTEMPLATE_API_DOMAIN` in the iOS scheme and Android `gradle.properties`. Never `127.0.0.1`, `localhost`, or `0.0.0.0`.
- Mailbin for email testing at `/mailbin`
- Admin interface at `/madmin`
- Tailwind CSS compiled by tailwindcss-rails gem
Expand Down
4 changes: 0 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ gem "turbo-rails", "~> 2.0.3"
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails", "~> 1.0", ">= 1.0.2"

# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder", "~> 2.14"

# Solid adapters for queue, cache, and cable (database-backed, no Redis needed)
gem "solid_queue"
gem "solid_cable"
Expand All @@ -49,7 +46,6 @@ gem "aasm"
gem "after_commit_everywhere", "~> 1.6"
gem "config"
gem "acts_as_tenant"
gem "inline_svg", "~> 1.10"
gem "pagy", "~> 43"
gem "seed-fu", "~> 2.3"
gem "whenever", require: false
Expand Down
80 changes: 33 additions & 47 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (4.1.1)
bigdecimal (4.1.2)
bindex (0.8.1)
bootsnap (1.23.0)
bootsnap (1.24.1)
msgpack (~> 1.2)
brakeman (8.0.4)
racc
Expand Down Expand Up @@ -142,7 +142,7 @@ GEM
devise (> 3.5.2, < 5)
rails (>= 4.2.0, < 8.2)
drb (2.2.3)
erb (6.0.3)
erb (6.0.4)
erb_lint (0.9.0)
activesupport
better_html (>= 2.0.1)
Expand All @@ -153,12 +153,12 @@ GEM
erubi (1.13.1)
et-orbi (1.4.0)
tzinfo
ffi (1.17.3-aarch64-linux-gnu)
ffi (1.17.3-arm-linux-gnu)
ffi (1.17.3-arm64-darwin)
ffi (1.17.3-x86-linux-gnu)
ffi (1.17.3-x86_64-darwin)
ffi (1.17.3-x86_64-linux-gnu)
ffi (1.17.4-aarch64-linux-gnu)
ffi (1.17.4-arm-linux-gnu)
ffi (1.17.4-arm64-darwin)
ffi (1.17.4-x86-linux-gnu)
ffi (1.17.4-x86_64-darwin)
ffi (1.17.4-x86_64-linux-gnu)
fugit (1.12.1)
et-orbi (~> 1.4)
raabro (~> 1.4)
Expand All @@ -179,22 +179,13 @@ GEM
activesupport (>= 6.0.0)
railties (>= 6.0.0)
iniparse (1.5.0)
inline_svg (1.10.0)
activesupport (>= 3.0)
nokogiri (>= 1.6)
io-console (0.8.2)
irb (1.17.0)
irb (1.18.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jbuilder (2.14.1)
actionview (>= 7.0.0)
activesupport (>= 7.0.0)
json (2.19.3)
json-schema (6.2.0)
addressable (~> 2.8)
bigdecimal (>= 3.1, < 5)
json (2.19.4)
jsonapi-serializer (2.2.0)
activesupport (>= 4.2)
language_server-protocol (3.17.0.5)
Expand Down Expand Up @@ -222,13 +213,11 @@ GEM
turbo-rails
marcel (1.1.0)
matrix (0.4.3)
mcp (0.10.0)
json-schema (>= 4.1)
mini_magick (5.3.1)
logger
mini_mime (1.1.5)
mini_portile2 (2.8.9)
minitest (6.0.4)
minitest (6.0.6)
drb (~> 2.0)
prism (~> 1.5)
minitest-mock (5.27.0)
Expand All @@ -245,7 +234,7 @@ GEM
msgpack (1.8.0)
multi_xml (0.8.1)
bigdecimal (>= 3.1, < 5)
net-imap (0.6.3)
net-imap (0.6.4)
date
net-protocol
net-pop (0.1.2)
Expand All @@ -255,31 +244,31 @@ GEM
net-smtp (0.5.1)
net-protocol
nio4r (2.7.5)
nokogiri (1.19.2)
nokogiri (1.19.3)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.19.2-aarch64-linux-gnu)
nokogiri (1.19.3-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-arm-linux-gnu)
nokogiri (1.19.3-arm-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-arm64-darwin)
nokogiri (1.19.3-arm64-darwin)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-darwin)
nokogiri (1.19.3-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-linux-gnu)
nokogiri (1.19.3-x86_64-linux-gnu)
racc (~> 1.4)
orm_adapter (0.5.0)
ostruct (0.6.3)
overcommit (0.69.0)
childprocess (>= 0.6.3, < 6)
iniparse (~> 1.4)
rexml (>= 3.3.9)
pagy (43.5.1)
pagy (43.5.3)
json
uri
yaml
parallel (1.27.0)
parser (3.3.10.2)
parallel (2.1.0)
parser (3.3.11.1)
ast (~> 2.4.1)
racc
pg (1.6.3)
Expand All @@ -291,15 +280,15 @@ GEM
prettyprint
prettyprint (0.2.0)
prism (1.9.0)
propshaft (1.3.1)
propshaft (1.3.2)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
psych (5.3.1)
date
stringio
public_suffix (7.0.5)
puma (8.0.0)
puma (8.0.1)
nio4r (~> 2.0)
pundit (2.5.2)
activesupport (>= 3.0.0)
Expand Down Expand Up @@ -351,7 +340,7 @@ GEM
erb
psych (>= 4.0.0)
tsort
regexp_parser (2.11.3)
regexp_parser (2.12.0)
reline (0.6.3)
io-console (~> 0.5)
resend (1.3.0)
Expand All @@ -361,19 +350,18 @@ GEM
actionpack (>= 7.0)
railties (>= 7.0)
rexml (3.4.4)
rubocop (1.85.1)
rubocop (1.86.1)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
mcp (~> 0.6)
parallel (~> 1.10)
parallel (>= 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.49.0)
rubocop-ast (1.49.1)
parser (>= 3.3.7.2)
prism (~> 1.7)
rubocop-performance (1.26.1)
Expand Down Expand Up @@ -428,11 +416,11 @@ GEM
tailwindcss-rails (4.4.0)
railties (>= 7.0.0)
tailwindcss-ruby (~> 4.0)
tailwindcss-ruby (4.2.1)
tailwindcss-ruby (4.2.1-aarch64-linux-gnu)
tailwindcss-ruby (4.2.1-arm64-darwin)
tailwindcss-ruby (4.2.1-x86_64-darwin)
tailwindcss-ruby (4.2.1-x86_64-linux-gnu)
tailwindcss-ruby (4.2.4)
tailwindcss-ruby (4.2.4-aarch64-linux-gnu)
tailwindcss-ruby (4.2.4-arm64-darwin)
tailwindcss-ruby (4.2.4-x86_64-darwin)
tailwindcss-ruby (4.2.4-x86_64-linux-gnu)
thor (1.5.0)
timeout (0.6.1)
tsort (0.2.0)
Expand Down Expand Up @@ -494,8 +482,6 @@ DEPENDENCIES
erb_lint
image_processing (~> 1.12)
importmap-rails
inline_svg (~> 1.10)
jbuilder (~> 2.14)
jsonapi-serializer
madmin (~> 2.0)
mailbin
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ For more information, visit [nativeapptemplate.com](https://nativeapptemplate.co
- **[pundit](https://github.com/varvet/pundit)**
- **[acts_as_tenant](https://github.com/ErwinM/acts_as_tenant)**
- **[pagy](https://github.com/ddnexus/pagy)**
- **[Turbo](https://turbo.hotwired.dev/)** (real-time page updates for Number Tags Webpage)
- **Test** (Minitest)

### Included Features
Expand All @@ -31,7 +30,7 @@ For more information, visit [nativeapptemplate.com](https://nativeapptemplate.co
- Email Confirmation
- Forgot Password
- CRUD Operations for Shops (Create/Read/Update/Delete)
- CRUD Operations for Shops' Nested Resource, Number Tags (ItemTags) (Create/Read/Update/Delete)
- CRUD Operations for Shops' Nested Resource, Item Tags (Create/Read/Update/Delete)
- URL Path-Based Multitenancy (prepends `/:account_id/` to URLs)
- User Invitation to Organizations
- Role-Based Permissions and Access Control
Expand Down Expand Up @@ -85,7 +84,7 @@ bin/setup

## Running NativeAppTemplate API on your Wi-Fi

Copy `.env.sample` to `.env` and set `HOST` to your current Wi-Fi IP. On macOS: `ipconfig getifaddr en0`. `bin/dev` binds Rails to that address so the dev server is reachable from both the host browser and from any phone on the same network at `http://<wifi-ip>:3000`. When your Wi-Fi IP changes, update `HOST` here and the matching `NATEMPLATE_API_DOMAIN` in the mobile apps (Xcode scheme for iOS, `~/.gradle/gradle.properties` for Android) — Rails fails loudly if `HOST` is unset, which keeps the three sides honest. Never use `127.0.0.1`, `localhost`, or `0.0.0.0`.
Copy `.env.sample` to `.env` and set `HOST` to your current Wi-Fi IP. On macOS: `ipconfig getifaddr en0`. `bin/dev` binds Rails to that address so the dev server is reachable from both the host browser and from any phone on the same network at `http://<wifi-ip>:3000`. When your Wi-Fi IP changes, update `HOST` here and the matching `NATIVEAPPTEMPLATE_API_DOMAIN` in the mobile apps (Xcode scheme for iOS, `~/.gradle/gradle.properties` for Android) — Rails fails loudly if `HOST` is unset, which keeps the three sides honest. Never use `127.0.0.1`, `localhost`, or `0.0.0.0`.

To run your application, you'll use the `bin/dev` command:

Expand Down
30 changes: 13 additions & 17 deletions app/controllers/api/v1/shopkeeper/item_tags_controller.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
class Api::V1::Shopkeeper::ItemTagsController < Api::V1::Shopkeeper::BaseController
before_action :set_shop, only: %i[index create]
before_action :set_item_tag, only: %i[show update destroy complete reset]
before_action :set_item_tag, only: %i[show update destroy complete idle]

def index
authorize ItemTag

@pagy, @item_tags = pagy(
@shop.item_tags.order(queue_number: :asc).includes(:shop),
@shop.item_tags.order(:position, :name).includes(:shop),
limit: params[:page].present? ? Pagy::OPTIONS[:limit] : 1000
)

Expand Down Expand Up @@ -53,27 +53,23 @@ def destroy
def complete
authorize @item_tag

options = {}
options[:include] = [:shop]

if @item_tag.completed?
# Purge ItemTagSerializer cache
@item_tag.already_completed = true
@item_tag.save!(validate: false)
render json: ItemTagSerializer.new(@item_tag, options).serializable_hash and return
if @item_tag.may_complete?
@item_tag.completed_by = current_shopkeeper
@item_tag.completed_at = Time.current
@item_tag.complete!
end

@item_tag.complete_tag!(current_shopkeeper)

options = {}
options[:include] = [:shop]
render json: ItemTagSerializer.new(@item_tag, options).serializable_hash
end

def reset
def idle
authorize @item_tag

ApplicationRecord.transaction do
@item_tag.reset!
end
@item_tag.completed_by_id = nil
@item_tag.completed_at = nil
@item_tag.idle!

render json: ItemTagSerializer.new(@item_tag).serializable_hash
end
Expand All @@ -91,6 +87,6 @@ def set_item_tag
end

def item_tag_params
params.require(:item_tag).permit(:queue_number)
params.require(:item_tag).permit(:name, :description, :position, :state)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ def index
android_app_version: current_android_app_version,
should_update_privacy: should_update_privacy,
should_update_terms: should_update_terms,
maximum_queue_number_length: ConfigSettings.maximum_queue_number_length,
shop_limit_count: ConfigSettings.shop.limit_count,
account_limit_count: ConfigSettings.account.limit_count,
accounts_shopkeeper_limit_count: ConfigSettings.accounts_shopkeeper.limit_count
Expand Down
12 changes: 1 addition & 11 deletions app/controllers/api/v1/shopkeeper/shops_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class Api::V1::Shopkeeper::ShopsController < Api::V1::Shopkeeper::BaseController
before_action :set_shop, only: %i[show update destroy reset]
before_action :set_shop, only: %i[show update destroy]

def index
authorize Shop
Expand Down Expand Up @@ -53,16 +53,6 @@ def destroy
render json: {status: 200}, status: :ok
end

def reset
authorize @shop

ApplicationRecord.transaction do
@shop.reset!
end

render json: {status: 200}, status: :ok
end

private

def set_shop
Expand Down
5 changes: 0 additions & 5 deletions app/controllers/display/base_controller.rb

This file was deleted.

Loading