Commit graph

1853 commits

Author SHA1 Message Date
ee918c2eda
feat: add best-effort subscription migration to new price 2026-03-06 13:52:28 -06:00
a813f56d1d
feat: add StripeClient.update_subscription_price 2026-03-06 13:50:11 -06:00
3e74ac5897
feat: add StripeClient.create_price for metered billing 2026-03-06 13:47:54 -06:00
448ed20401
feat: dynamic global billing defaults from ApplicationSettings 2026-03-06 13:44:03 -06:00
a16ce2b9dd
feat: add decimal type support to ApplicationSetting 2026-03-06 13:34:37 -06:00
7d61d8fb0a
feat: seed global billing settings in application_settings 2026-03-06 13:26:50 -06:00
ffb61641bb
docs: design for dynamic global pricing configuration 2026-03-06 13:18:47 -06:00
2ae7a2680a
fix: clear stale Dokku deploy lock before pushing
cancel-in-progress kills the CI job mid-deploy but Dokku's server-side
lock persists, causing subsequent deploys to hang indefinitely.
2026-03-06 13:06:18 -06:00
9229e6e920
fix: remove internal details from public changelog 2026-03-06 13:03:36 -06:00
e161aaab83
docs: update changelogs for billing overrides and interface stats fix 2026-03-06 13:02:55 -06:00
cc53dd6a64
fix: access interface stats through latest_stat association
The template accessed if_in_octets/if_out_octets directly on the
Interface struct, but these fields live on InterfaceStat. Access
through interface.latest_stat with nil guard to prevent KeyError
when the association is not loaded.
2026-03-06 13:02:21 -06:00
9aec87636b
feat: per-organization billing override admin UI
Allow superadmins to override free device limits and per-device pricing
on a per-organization basis. Overrides cascade through subscription
limits, billing calculations, and user-facing settings display.

- Add custom_free_device_limit and custom_price_per_device to organizations
- Add billing_override_changeset with validation
- Update SubscriptionLimits.effective_device_limit to respect overrides
- Update Billing to use effective free count and price per device
- Add Admin.update_billing_overrides with audit logging
- Add override editing UI to /admin/organizations
- Update org settings page to show effective limits/pricing
2026-03-06 13:02:05 -06:00
1d98cda79d
fix: configure Watchtower to only monitor agent container
Add WATCHTOWER_SCOPE=towerops environment variable to generated
docker-compose templates. This prevents Watchtower from monitoring
unrelated containers on the same Docker host (e.g., Dokku apps).

Without scope filtering, Watchtower would attempt to monitor all
containers with watchtower.enable=true label, causing warnings
for missing images and unnecessary monitoring overhead.
2026-03-06 12:38:44 -06:00
d17b7baba4
fix: correct 'More' navigation translation from 'or' to 'More' 2026-03-06 12:26:18 -06:00
721c1f2481
feat: branch-based deployment (main → staging, production → prod)
- main branch: auto-deploy to Dokku staging
- production branch: build Docker image and deploy to K8s production
- Add DEPLOYMENT.md with workflow documentation
- Create production branch for manual production deployments

Breaking change: pushing to main no longer deploys to production
2026-03-06 12:22:05 -06:00
3a5da6f68c
test(activity_feed): add comprehensive test coverage
- Test empty activity list
- Test preseem sync logs with correct DateTime format
- Test duration formatting with integer precision
- Test sync logs without duration
- Test grouping by minute
- Test sorting by timestamp descending
- Test limit parameter
- Test date range filtering
- Test organization isolation
- Test different sync statuses (success, failed, partial)
- Test count_by_type functionality
2026-03-06 12:22:05 -06:00
70718a53dc
fix(activity_feed): show integer milliseconds without decimal point 2026-03-06 12:22:04 -06:00
73daad48a5
fix: convert NaiveDateTime to DateTime for activity feed sorting
- date_trunc fragment returns NaiveDateTime without timezone
- Convert to UTC DateTime before returning from preseem sync query
- Fixes DateTime.compare/2 function clause error when sorting activities
- All activity timestamps now consistently use DateTime with timezone
2026-03-06 12:22:04 -06:00
2ba5a3fd7b
fix: replace max(uuid) with array_agg for preseem sync logs
- PostgreSQL's max() function doesn't work on UUID types
- Use array_agg to get first ID from grouped results instead
- Matches pattern already used for status field
- Fixes crash on /activity page when preseem sync logs exist
2026-03-06 12:22:04 -06:00
CI
bf7004c770 chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772816933-2a61626 [skip ci] 2026-03-06 17:16:12 +00:00
2a61626135
feat: allow script to work with both test and live Stripe keys
- Accept both sk_test_ and sk_live_ API keys
- Show mode indicator (TEST/LIVE) in output
- Adjust webhook URL based on mode (localhost for test, towerops.net for live)
- Add warning when using test mode
- Useful for testing billing setup before going live
2026-03-06 11:08:07 -06:00
13631595a7
fix: handle spaces in JSON when extracting Stripe IDs
- Update grep patterns to match JSON with spaces after colons
- Fixes false 'Error creating meter' message when meter created successfully
- Applies to meter ID and price ID extraction
2026-03-06 11:08:07 -06:00
3e721b9395
fix: check for existing billing meter before creating
- First check if a meter with 'devices_monitored' event exists
- Reuse existing meter ID if found
- Only create new meter if none exists
- Fixes error when meter already exists in Stripe account
2026-03-06 11:08:07 -06:00
d3aa602ba4
feat: add production Stripe billing setup script
- Interactive script to create production billing meter and price
- Prompts for live API key and product ID
- Creates billing meter with 'devices_monitored' event
- Creates metered price at $1/device/month
- Outputs kubectl command for creating k8s secret
- Includes setup instructions for webhook configuration
2026-03-06 11:08:06 -06:00
d0e7eb4308
feat: add Stripe meter ID configuration
- Add stripe_meter_id to dev, runtime, and test configs
- Add STRIPE_METER_ID to k8s deployment secret references
- Use real Stripe meter and price IDs from Stripe setup
- Meter: mtr_test_61UHPU067veEZ7bhl41S77kvnTfgyODY
- Price: price_1T81XBS77kvnTfgyPlw1jF8N ($1/device/month)
- Include setup script for Stripe billing configuration
2026-03-06 11:08:06 -06:00
20f05584dc
fix: use k8s secret for Stripe env vars instead of hardcoded values
- Changed from hardcoded placeholder values to secretKeyRef
- References towerops-billing secret (with optional: true)
- Won't crash if secret doesn't exist yet
- User can create secret later with real Stripe keys
2026-03-06 11:08:06 -06:00
7d2f1fd860
feat: add BillingSyncWorker to dev Oban cron schedule
- Enables daily billing sync at 3 AM UTC in development
- Matches production configuration for testing
- All 54 billing tests passing
2026-03-06 11:08:05 -06:00
3523676359
feat: configure Stripe environment variables for dev and k8s
- Add Stripe test API keys to dev.exs for local development
- Add placeholder Stripe env vars to k8s deployment to prevent startup crashes
- Includes secret_key, webhook_secret, and price_id configuration
2026-03-06 11:08:05 -06:00
4b4bb2668f
feat: add billing tab to organization settings
Implements Phase 6 of Stripe billing integration:
- Add Billing tab to organization settings page
- Display subscription status, device usage, and estimated costs
- "Upgrade to Paid Plan" button for free tier orgs
- "Manage Billing" button to access Stripe Customer Portal
- Billing information panel showing subscription details
- Support for dark mode and responsive design

Also fixes organization name truncation in top navigation:
- Long organization names now show with ellipsis instead of being cut off
- Added max-w-xs constraint and truncate class to org switcher button
2026-03-06 11:08:05 -06:00
CI
1c081623aa chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772813291-f832130 [skip ci] 2026-03-06 16:14:54 +00:00
f83213080f
stripe and email after signup 2026-03-06 10:07:27 -06:00
b3cff9afbb
stripe and email after signup 2026-03-06 10:07:27 -06:00
CI
43532007b8 chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772807346-b5e8e00 [skip ci] 2026-03-06 14:32:10 +00:00
b5e8e00dcb
perf(tests): aggressive timeout and delay reductions
Major reductions across test suite:
- Error handler backoff delays: 100ms→20ms, 50ms→10ms
- Sensor change detector refute_receive: 100ms→50ms
- Agent channel assert_receive: 5000ms→1000ms, 2000ms→500ms
- Agent channel assert_push: 5000ms→1000ms
- Deferred discovery timeout sleeps: 60ms→55ms
- Event logger sleeps: 25ms→10ms
- Validator test: 50,100 OIDs→50,001 (minimum to test rejection)

Performance: 28s → 26.8s (4.3% faster)
Total from baseline: 52s → 26.8s (48.5% faster)
2026-03-06 08:28:18 -06:00
CI
bc7922f476 chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772806694-acf7e55 [skip ci] 2026-03-06 14:21:09 +00:00
acf7e5548b
perf(tests): reduce event logger sleep from 25ms to 10ms
Reduce Process.sleep delays in event_logger_test from 25ms to 10ms.
These sleeps wait for async event logging to complete.

All tests still pass with shorter delay.
2026-03-06 08:17:31 -06:00
CI
a083c7069c chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772806349-1e072c7 [skip ci] 2026-03-06 14:15:35 +00:00
1e072c75e4
perf(tests): reduce assert/refute timeouts for faster tests
Reduce various test timeouts that were unnecessarily long:
- assert_push timeouts: 150ms → 75ms (6 tests in agent_channel_test)
- refute_receive timeouts: 200ms → 50ms (3 tests in worker tests)

With 50ms channel debounce, 75ms is sufficient for assert_push.
For refute_receive (expecting no message), 50ms is plenty.

Estimated savings: ~600ms across affected tests
2026-03-06 08:11:50 -06:00
CI
e47b08c44f chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772805892-52329cf [skip ci] 2026-03-06 14:11:25 +00:00
52329cf959
perf(tests): make device deletion delay configurable for faster tests
Make the 500ms device deletion delay configurable via application config.
Set to 10ms in test environment (vs 500ms in production).

This sleep waits for in-flight polling jobs to complete before deleting
a device. In tests with mocked jobs, this delay is unnecessary.

Affected tests:
- All device deletion tests (were 500-650ms, now ~100-150ms)
- Equipment context tests
- API controller tests
- LiveView tests with device deletion

Performance: 28.3s → 25.2s (11% faster)
Total improvement from baseline: 52s → 25.2s (51.5% faster)
2026-03-06 08:04:08 -06:00
CI
1038cc3d42 chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772805491-0c7d195 [skip ci] 2026-03-06 14:01:06 +00:00
0c7d195e52
chore: remove backup files from sed operations 2026-03-06 07:57:30 -06:00
83d47d1502
perf(tests): remove/reduce Process.sleep calls for faster tests
- Remove all 25ms and 50ms sleeps from agent_channel_test
- Add poll_until helper for async DB operations (early exit on success)
- Reduce timeout test sleeps from 100ms to 60ms
- Reduce polling delays from 10ms to 5ms in multiple tests
- Remove unnecessary timestamp and background task sleeps
- Reduce circuit breaker recovery sleep from 150ms to 110ms

Performance: 30.3s → 28.3s (6.6% faster)
Total improvement from baseline: 52s → 28.3s (45.6% faster)
2026-03-06 07:57:30 -06:00
CI
4ebe215a90 chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772804771-b5cf562 [skip ci] 2026-03-06 13:49:06 +00:00
b5cf562e55
fix(tests): enable TOTP in final AdminControllerTest
Enable TOTP in impersonation test for superuser authentication flow.
2026-03-06 07:45:28 -06:00
CI
be9ebff63e chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772804218-9e525aa [skip ci] 2026-03-06 13:39:48 +00:00
9e525aa7e2
fix(tests): enable TOTP in remaining test setups
Fixes TOTP-related test failures by adding enable_totp: true to setup blocks.

Updated test files:
- test/towerops_web/live/org/preseem_insights_live_test.exs
- test/towerops_web/live/agent_live/index_test.exs
- test/towerops_web/live/org/integrations_live_test.exs
- test/towerops_web/live/org/settings_live_members_test.exs
- test/towerops_web/live/org/settings_live_property_test.exs
- test/towerops_web/live/org/settings_live_test.exs
- test/towerops_web/live/device_live/show_test.exs
- test/towerops_web/controllers/admin_controller_test.exs

Progress: 148 failures → 66 failures
2026-03-06 07:36:19 -06:00
CI
3ed732fecc chore: update towerops-web image to git.mcintire.me/graham/towerops-web:main-1772803826-1f49e1f [skip ci] 2026-03-06 13:33:19 +00:00
1f49e1fba5
perf(tests): reduce Process.sleep calls in timeout tests
Optimizations:
- Deferred discovery tests: 500ms → 100ms sleeps (still > 50ms timeout)
- Event logger tests: 100ms → 50ms sleeps, added polling for early exit
- Saved ~2.4 seconds across affected tests (6 tests × 400ms each)

Changes:
- test/towerops/snmp/deferred_discovery_test.exs: reduce timeout test sleeps
- test/towerops/equipment/event_logger_test.exs: reduce sleeps, add polling
2026-03-06 07:27:35 -06:00
0ea54b63db
perf(tests): disable TOTP by default in fixtures for faster tests
**Performance improvement: 52s → 33.2s test suite (35% faster)**

Changes:
- Disable TOTP by default in user_fixture (was enabled for all 7400+ tests)
- Enable TOTP only where needed (auth flows, TOTP-specific tests)
- Update ConnCase helpers to enable TOTP (required for authenticated sessions)
- Update test setups that need TOTP for LiveView authentication

Impact:
- Eliminates unnecessary TOTP secret generation + DB writes for most tests
- Reduces Argon2 password hashing overhead across test suite
- 281 tests now properly handle TOTP requirements

Files updated:
- test/support/fixtures/accounts_fixtures.ex: enable_totp default false → true only when needed
- test/support/conn_case.ex: register_and_log_in_user helpers enable TOTP
- test/towerops/accounts_test.exs: TOTP-related describe blocks enable TOTP
- test/towerops_web/user_auth_test.exs: setup enables TOTP
- test/towerops_web/live/admin/*: admin LiveView tests enable TOTP
- test/towerops_web/live/org/preseem_devices_live_test.exs: enable TOTP
2026-03-06 07:21:52 -06:00