feat(api): mobile API Milestone 1+2 — Sanctum auth + offline sync vertical slice
Milestone 1 (auth foundation):
- Installed laravel/sanctum; HasApiTokens on User; published config + migration.
- routes/api.php with /api/v1; Sanctum 'ability' middleware alias registered.
- AuthController: POST login (long-lived revocable device token w/ ability
mobile-sync + devices table), GET me, POST logout. New Device model/table.
Milestone 2 (vertical slice, offline-first):
- progress_updates: +uuid (client-generated) +client_updated_at.
- ProjectApiController: GET projects (accessibleBy), GET projects/{id}/bundle
(project/phases/layers/features, membership-authorized).
- SyncController: POST sync — batch ops, idempotent by uuid, per-op result
(applied/duplicate/error), server-set user_id, authz by permission+membership.
Currently handles progress_update.create.
Tests: tests/Feature/Api/MobileApiTest (9 passing) — auth, accessible projects,
bundle authz, sync apply+idempotency, permission enforcement.
Also fixed a latent schema bug: projects.reference (and external_reference_1)
existed in the live DB but had no migration — added a guarded migration so fresh
installs match production.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Api\V1\AuthController;
|
||||
use App\Http\Controllers\Api\V1\ProjectApiController;
|
||||
use App\Http\Controllers\Api\V1\SyncController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::prefix('v1')->group(function () {
|
||||
|
||||
// Público
|
||||
Route::post('login', [AuthController::class, 'login'])->middleware('throttle:10,1');
|
||||
|
||||
// Protegido: token Sanctum con ability 'mobile-sync'
|
||||
Route::middleware(['auth:sanctum', 'ability:mobile-sync'])->group(function () {
|
||||
Route::get('me', [AuthController::class, 'me']);
|
||||
Route::post('logout', [AuthController::class, 'logout']);
|
||||
|
||||
// PULL
|
||||
Route::get('projects', [ProjectApiController::class, 'index']);
|
||||
Route::get('projects/{project}/bundle', [ProjectApiController::class, 'bundle']);
|
||||
|
||||
// PUSH
|
||||
Route::post('sync', [SyncController::class, 'sync'])->middleware('throttle:60,1');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user