feat(notifications): scaffold GET /v1/account/alerts/:alertId/track endpoint

Adds a public-scope tracking-pixel endpoint skeleton that always returns a
1x1 transparent PNG. The body is intentionally minimal so the email-tracking
read-flag flip can be wired up cleanly in Wave 3 (ST14) once the JWT decode
and DB write paths are designed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jake Barnby
2026-05-06 13:44:58 +12:00
co-authored by Claude Opus 4.7
parent 0ce3978f2c
commit a0400d2e93
2 changed files with 71 additions and 1 deletions
@@ -0,0 +1,68 @@
<?php
namespace Appwrite\Platform\Modules\Account\Http\Alerts\Track;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\Validator\UID;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
use Utopia\Validator\Text;
class Get extends Action
{
use HTTP;
public static function getName(): string
{
return 'getAlertTrack';
}
public function __construct()
{
$this
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/account/alerts/:alertId/track')
->desc('Track alert')
->groups(['api', 'account'])
->label('scope', 'public')
->label('sdk', new Method(
namespace: 'account',
name: 'getAlertTrack',
description: '/docs/references/account/get-alert-track.md',
auth: [AuthType::SESSION, AuthType::JWT],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_NONE,
),
],
contentType: ContentType::IMAGE_PNG,
))
->param('alertId', '', new UID(), 'Alert ID.')
->param('jwt', '', new Text(2048, 0), 'Tracking token.', true)
->inject('response')
->inject('dbForPlatform')
->callback($this->action(...));
}
public function action(
string $alertId,
string $jwt,
Response $response,
Database $dbForPlatform,
): void {
// 1x1 transparent PNG. Wave 3 (ST14) will replace this body with
// JWT decode + read-flag flip; the skeleton always returns the pixel.
$pixel = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==');
$response
->setContentType('image/png')
->addHeader('Cache-Control', 'no-store')
->send($pixel);
}
}
@@ -12,6 +12,7 @@ use Appwrite\Platform\Modules\Account\Http\Account\MFA\RecoveryCodes\Create as C
use Appwrite\Platform\Modules\Account\Http\Account\MFA\RecoveryCodes\Get as GetRecoveryCodes;
use Appwrite\Platform\Modules\Account\Http\Account\MFA\RecoveryCodes\Update as UpdateRecoveryCodes;
use Appwrite\Platform\Modules\Account\Http\Account\MFA\Update as UpdateMfa;
use Appwrite\Platform\Modules\Account\Http\Alerts\Track\Get as TrackAlert;
use Utopia\Platform\Service;
class Http extends Service
@@ -29,6 +30,7 @@ class Http extends Service
->addAction(UpdateRecoveryCodes::getName(), new UpdateRecoveryCodes())
->addAction(GetRecoveryCodes::getName(), new GetRecoveryCodes())
->addAction(CreateChallenge::getName(), new CreateChallenge())
->addAction(UpdateChallenge::getName(), new UpdateChallenge());
->addAction(UpdateChallenge::getName(), new UpdateChallenge())
->addAction(TrackAlert::getName(), new TrackAlert());
}
}