refactor(ai): remove AiConsentSettings feature flag (#619)
## What Removes the `AiConsentSettings` Laravel Pennant feature flag. The AI consent management UI — the toggle in **Billing settings** and the banner in **Transactions** — is now available to all users automatically, no longer gated behind the flag. The underlying AI consent functionality (model, controller, routes, `User` consent methods) is unchanged; only the gate that hid its UI was removed. ## Changes - Delete `app/Features/AiConsentSettings.php`. - `HandleInertiaRequests`: drop the `aiConsentSettings` shared prop and its resolution. - Frontend: render `AiConsentSection` and the transactions consent banner unconditionally; drop the now-unused `aiConsentSettings` type and `features` destructuring. - Tests: remove the two flag-specific assertions in `AiConsentSettingsTest` (consent-state coverage kept), update `InertiaSharedDataTest`, and switch `FeatureEnableCommandTest` to `CalculateBalancesOnImport` as its example feature. ## Testing - `php artisan test` on the affected suites — 13 passed. - `vendor/bin/pint`, `bun run format`, `bun run lint` — clean.
This commit is contained in:
parent
10442c1e32
commit
4120e12861
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Features;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
class AiConsentSettings
|
||||
{
|
||||
/**
|
||||
* Resolve the feature's initial value.
|
||||
*
|
||||
* Off by default; enable per user with
|
||||
* `php artisan feature:enable AiConsentSettings user@example.com`
|
||||
* to surface AI consent management outside of onboarding (billing
|
||||
* settings toggle + transactions banner).
|
||||
*/
|
||||
public function resolve(?User $user): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ namespace App\Http\Middleware;
|
|||
|
||||
use App\Enums\BankingConnectionStatus;
|
||||
use App\Enums\BankingProvider;
|
||||
use App\Features\AiConsentSettings;
|
||||
use App\Features\CalculateBalancesOnImport;
|
||||
use App\Models\BankingConnection;
|
||||
use App\Services\CurrencyOptions;
|
||||
|
|
@ -179,19 +178,16 @@ class HandleInertiaRequests extends Middleware
|
|||
return [
|
||||
'cashflow' => true,
|
||||
'calculateBalancesOnImport' => false,
|
||||
'aiConsentSettings' => false,
|
||||
];
|
||||
}
|
||||
|
||||
$features = Feature::for($user)->values([
|
||||
CalculateBalancesOnImport::class,
|
||||
AiConsentSettings::class,
|
||||
]);
|
||||
|
||||
return [
|
||||
'cashflow' => true,
|
||||
'calculateBalancesOnImport' => $features[CalculateBalancesOnImport::class] !== false,
|
||||
'aiConsentSettings' => $features[AiConsentSettings::class] !== false,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -476,7 +476,7 @@ function AiConsentSection({
|
|||
}
|
||||
|
||||
export default function Billing() {
|
||||
const { auth, pricing, locale, features, hasAiConsent, refund } = usePage<
|
||||
const { auth, pricing, locale, hasAiConsent, refund } = usePage<
|
||||
SharedData & { hasAiConsent: boolean; refund?: RefundInfo }
|
||||
>().props;
|
||||
const isDemoAccount = auth?.isDemoAccount ?? false;
|
||||
|
|
@ -507,12 +507,10 @@ export default function Billing() {
|
|||
/>
|
||||
)}
|
||||
|
||||
{features.aiConsentSettings && (
|
||||
<AiConsentSection
|
||||
initialConsent={hasAiConsent}
|
||||
hasProPlan={hasProPlan}
|
||||
/>
|
||||
)}
|
||||
<AiConsentSection
|
||||
initialConsent={hasAiConsent}
|
||||
hasProPlan={hasProPlan}
|
||||
/>
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
</AppLayout>
|
||||
|
|
|
|||
|
|
@ -437,12 +437,11 @@ export default function Transactions({
|
|||
lastVisitAt,
|
||||
}: Props) {
|
||||
const locale = useLocale();
|
||||
const { auth, features } = usePage<SharedData>().props;
|
||||
const { auth } = usePage<SharedData>().props;
|
||||
const [aiConsentResolved, setAiConsentResolved] = useState(false);
|
||||
const [aiConsentSaving, setAiConsentSaving] = useState(false);
|
||||
const showAiConsentBanner =
|
||||
auth.hasProPlan &&
|
||||
features.aiConsentSettings &&
|
||||
!hasAiConsent &&
|
||||
!aiConsentPromptDismissed &&
|
||||
!aiConsentResolved;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ export interface NavDivider {
|
|||
export interface Features {
|
||||
cashflow: boolean;
|
||||
calculateBalancesOnImport: boolean;
|
||||
aiConsentSettings: boolean;
|
||||
}
|
||||
|
||||
export interface ExpiredBankingConnectionNotification {
|
||||
|
|
|
|||
|
|
@ -1,31 +1,10 @@
|
|||
<?php
|
||||
|
||||
use App\Features\AiConsentSettings;
|
||||
use App\Models\User;
|
||||
use Inertia\Testing\AssertableInertia as Assert;
|
||||
use Laravel\Pennant\Feature;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
test('ai consent settings flag is off by default in shared props', function () {
|
||||
$user = User::factory()->onboarded()->create();
|
||||
|
||||
actingAs($user)->withoutVite()->get(route('dashboard'))
|
||||
->assertInertia(fn (Assert $page) => $page
|
||||
->where('features.aiConsentSettings', false)
|
||||
);
|
||||
});
|
||||
|
||||
test('ai consent settings flag is exposed when activated for the user', function () {
|
||||
$user = User::factory()->onboarded()->create();
|
||||
Feature::for($user)->activate(AiConsentSettings::class);
|
||||
|
||||
actingAs($user)->withoutVite()->get(route('dashboard'))
|
||||
->assertInertia(fn (Assert $page) => $page
|
||||
->where('features.aiConsentSettings', true)
|
||||
);
|
||||
});
|
||||
|
||||
test('billing page reports current ai consent state', function () {
|
||||
config(['subscriptions.enabled' => true]);
|
||||
$user = User::factory()->onboarded()->create();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<?php
|
||||
|
||||
use App\Features\AiConsentSettings;
|
||||
use App\Features\CalculateBalancesOnImport;
|
||||
use App\Models\User;
|
||||
use Laravel\Pennant\Feature;
|
||||
|
||||
test('enables a feature for a percentage of users', function () {
|
||||
$users = User::factory()->count(10)->create();
|
||||
|
||||
$this->artisan('feature:enable', ['feature' => 'AiConsentSettings', 'target' => '40%'])
|
||||
$this->artisan('feature:enable', ['feature' => 'CalculateBalancesOnImport', 'target' => '40%'])
|
||||
->expectsOutputToContain('enabled for 4 users')
|
||||
->assertSuccessful();
|
||||
|
||||
$enabled = $users->filter(fn (User $user) => Feature::for($user)->active(AiConsentSettings::class));
|
||||
$enabled = $users->filter(fn (User $user) => Feature::for($user)->active(CalculateBalancesOnImport::class));
|
||||
|
||||
expect($enabled)->toHaveCount(4);
|
||||
});
|
||||
|
|
@ -19,6 +19,6 @@ test('enables a feature for a percentage of users', function () {
|
|||
test('rejects an out-of-range percentage', function () {
|
||||
User::factory()->create();
|
||||
|
||||
$this->artisan('feature:enable', ['feature' => 'AiConsentSettings', 'target' => '0%'])
|
||||
$this->artisan('feature:enable', ['feature' => 'CalculateBalancesOnImport', 'target' => '0%'])
|
||||
->assertFailed();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ test('shared feature flags do not include coinbase flag', function () {
|
|||
expect($props['features'])->toBe([
|
||||
'cashflow' => true,
|
||||
'calculateBalancesOnImport' => false,
|
||||
'aiConsentSettings' => false,
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue