Commands Queues Metadata Tracking Internal Docs 2026 05 06
Internal Docs Expansion: Commands, Queues, Metadata, Assets, Dashboards, Tracking — 2026-05-06
Update Summary
Researched a list of artisan commands, the Tadabase queue topology, the per-app metadata model, the asset pipeline, the dashboard signed-iframe flow, and the user/app usage tracking commands directly against the appifany2 codebase. Wrote a new technical doc for each topic in exported-articles/internal/, slotted into the appropriate sub-folder. Extended the existing moving-apps-between-databases.html with a worked example for the requested batch invocation.
Why
These topics either had no internal doc at all or had only a customer-facing reference. Staff needed a single, indexed deep-dive per topic that captures: the actual command signature, the call graph, the queue / connection mapping, the env flags, and the gotchas we keep re-learning. The internal portal already has docs at this depth for App Lifecycle, Backup/Restore, and Workflows; this round extends the same shape to the remaining topics.
Files Created / Updated
Path (relative to exported-articles/) | Change | Covers |
|---|---|---|
internal/App Management/moving-apps-between-databases.html | Updated — added "Batch Move Walkthrough" section | Worked example for sudo php artisan move-app-new --batch_id=2 --db_id=200 --update-db-info=1; mysqldump internals (backup_reader_host, env path overrides, log-table split, --mode=local); batch-specific gotchas. |
internal/Code & Implementation/run-app-script-types.html | Created | The php artisan run-app-script {type} command — signature, ~130 known case types organized by category (schema migrations, field/object fixes, default-data seeders, indexes, tracking, webhook tables, workflow infra, auth/security, PDF, AI, debug), the case-body skeleton, and rules for safely running and writing scripts. |
internal/Code & Implementation/queues-and-workers.html | Created | Every queue used in the codebase (~25 distinct names), Horizon supervisor map for prod & local, retry_after pitfalls (incl. redis-1000's misleading 1800s value), per-app override columns (qc, {name}_queue) and how getQueueConnection() / getQueueName() resolve them, and the "not in Horizon" warning for queues without supervisors. |
internal/Backups & Restores/restore-app-command.html | Created | php artisan restore-app end-to-end — option reference, full execution flow (Maintenance flip, S3 download, mysql < file.sql, AppRestore audit row, completion email to hitesh@ + moe@), APP_RESTORE_COMMAND / APP_BACKUP_AWS_COMMAND envs, gotchas (no auto-pre-backup, raw exec() failure swallowing, stuck-Maintenance recovery). |
internal/App Management/copy-app-command.html | Created | php artisan copy-app — token replacement ({appName}, {date}), --copy_data default behavior, --skip_data suffix matching, the ClientApp::copyApp() internal flow (default core tables list, trial reset rules, async CopyApp2ndStepJob path on the copy-owner-app queue), gotchas (slug collisions, same-DB constraint, plan inheritance, --log_insert_query output volume). |
internal/App Management/app-metadata-system.html | Created | Master-vs-per-app data model — users, client_apps, db_infos on the master tier; the full catalog of app_<id>_* tables grouped by schema/content/log, with retention notes for each log table; deep-dive on app_<id>_objects (the field metadata heart, including parent, last_number, f1/f2, metas); how setDbInfo rewrites config('database.connections.appMysql.*') at runtime; gotchas around connection reuse in long-lived workers. |
internal/Code & Implementation/app-assets-pipeline.html | Created | The asset pipeline — TB_ASSET_API_URL, the three Appifany2 controllers (TbAssetController, TbAppDashboardController, TbUserDashboardController), Guzzle server-to-server signed-iframe flow, encoded-id usage, generateToken / verifyToken 5-minute window, the app-data-js per-app JS bundle pipeline (AppDataJsJob, app-data-js queue, --onQueue=0 inline mode, updateUID trigger). |
internal/App Management/user-and-app-dashboards.html | Created | User Dashboard vs App Dashboard — routes, end-to-end signing flow, where each metric on the dashboard sources from (live per-app DB query / app_trackings / user_app_stats), the security model (auth required, encoded ids, app-not-in-Maintenance, 5-min token), troubleshooting playbook ("dashboard says 0 records," "yesterday's chart hasn't updated," etc.). |
internal/App Management/user-and-app-tracking.html | Created | The four ways usage gets counted — tb-app-track (per-app rollup into app_trackings), tb-user-track (per-user into user_trackings), tb-track (orchestrator + live event hook from BaseModel), and user-app-stats (daily snapshot into user_app_stats, runs at 01:00). Includes "when to run which" decision table and the gotchas (per-app connection reuse, soft-deleted apps still counted, --type takes single key only). |
Research Method
- Read every command file in
appifany2/app/Console/Commands/referenced by the request, end-to-end. - Pulled the schedule wiring from
app/Console/Kernel.phpand the queue topology fromconfig/queue.php+config/horizon.php. - Grepped
onQueue(andonConnection(across the entire codebase to enumerate every distinct queue name actually dispatched to (~25 unique queues found across commands, jobs, controllers, models, library helpers). - Read
ClientApp::moveAppNew,ClientApp::copyApp,ClientApp::getQueueConnection,ClientApp::getQueueName,ClientApp::updateUIDfor the model-side specifics. - Read the three Tb*Controller asset/dashboard controllers and the matching
routes/web-client.phpentries for the signed-iframe flow. - Cross-referenced existing internal docs (App Lifecycle, Backup/Restore, AI Queue, Workflows, Tracking Buffer) so the new docs link forward/back instead of duplicating.
Coverage vs. Request
| Requested Topic | New / Updated Doc |
|---|---|
sudo php artisan move-app-new --batch_id=2 --db_id=200 --update-db-info=1 | Updated moving-apps-between-databases.html with a Batch Move Walkthrough. |
All options in php artisan run-app-script {option} | run-app-script-types.html |
| All queues and how they work | queues-and-workers.html |
sudo php artisan restore-app --id=1247848 --db_id=149 --update_id=0 | restore-app-command.html |
sudo php artisan copy-app --app_id=46246 --name=DavidWrightTest ... | copy-app-command.html |
| How app metadata is created and tracked | app-metadata-system.html |
| App Assets | app-assets-pipeline.html |
| User and App Dashboards | user-and-app-dashboards.html |
| User tracking for total usage | user-and-app-tracking.html |
Codebase Changes
No code changes. This was a documentation-only pass; the appifany2 source was read-only research material. Each new doc cross-references the source files it draws from, so a reader can jump from doc to code in one step.
Items Flagged During Research
redis-1000connection'sretry_afteris 1800 seconds, not 1000 (the name reflects an older value). Documented inqueues-and-workers.html; worth renaming the connection key once a deploy window allows.- The
move-appqueue is dispatched to but is NOT in any Horizon supervisor's queue list. Manualqueue:work --queue=move-appis required to drain it. Same applies torapid-export,exporthitesh,batch-update,batch-delete,hubspotsync,api-usage,api-user-usage,ai-prompt-usage,ai-component-parallel,ai-verification-queue,tb-events, andapp-to-install. Either Horizon needs entries added or each queue needs a documented external worker. - SQS credentials are hardcoded in
config/queue.php. Should move to env to allow rotation without a deploy. - App-dashboard authorization is implicit. The controller checks auth + maintenance, but does not explicitly verify the authenticated user owns the app whose id is in the URL. Defense in depth would add an ownership check.
- Default
APP_RESTORE_COMMANDinRestoreAppCommand.phphardcodes the production cluster + DB password. Should be env-only with no hardcoded fallback. - The completion email for restores goes to
hitesh@tadabase.ioandmoe@tadabase.ioonly. Customer-initiated restores from the builder UI rely on a different code path for customer notification — verify both still notify the customer when needed.
We'd love to hear your feedback.