perlsky is a Perl 5 implementation of an AT Protocol Personal Data Server.
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

Split self-service invite flows from extended API suite

alice 7fd27f23 b532fb54

+78 -25
+5 -4
docs/TEST_AUDIT.md
··· 13 13 The current baseline for saying "the audited suite is green" is: 14 14 15 15 - `prove -lr t` 16 - - latest full green result in the realigned Meridian worktree: `Files=57, Tests=3051` 16 + - latest full green result in the realigned Meridian worktree: `Files=58, Tests=3053` 17 17 - `prove -lv t/server-auth.t` 18 18 - `perl -c script/differential-validate` 19 19 - `PERLSKY_RUN_REFERENCE_DIFF=1 prove -lv t/reference-differential.t` ··· 116 116 Current suite counts by bucket: 117 117 118 118 - `direct reference differential`: `5` 119 - - `audited local regression`: `39` 119 + - `audited local regression`: `40` 120 120 - `local correctness/infrastructure`: `13` 121 121 122 122 | Test file | Bucket | Current note | ··· 140 140 | `t/email-confirmation.t` | audited local regression | intentionally testing-friendly email flow plus strict missing-email and invalid-email validation semantics | 141 141 | `t/email-update-helper.t` | audited local regression | shared email-update helper normalization, token revocation, and duplicate-email error semantics | 142 142 | `t/event-stream.t` | audited local regression | wire-format, malformed frame, and event decoding coverage | 143 - | `t/extended-api.t` | audited local regression | focused mixed coverage for self-service invite issuance and `applyWrites` after the identity/email, label, and blob/sync happy paths were split out | 143 + | `t/extended-api.t` | audited local regression | focused `applyWrites` happy-path and missing-delete behavior after the self-service invite, identity/email, label, and blob/sync happy paths were split out | 144 144 | `t/external-handle-update.t` | audited local regression | external-handle update semantics, including DID-resolution checks and empty-body success for external handle adoption | 145 145 | `t/external-surface.t` | audited local regression | focused external-surface coverage for repo/blob/account-status and missing-blob behavior after splitting discovery and label RPC checks into dedicated suites | 146 146 | `t/firehose.t` | audited local regression | repo subscription lifecycle, cursor, and CAR behavior | ··· 169 169 | `t/repo-api.t` | audited local regression | record mutation and read semantics, but still lighter than ideal on some negative/reference edge cases | 170 170 | `t/repo-firehose-car.t` | audited local regression | repo commit CAR shape and firehose interactions | 171 171 | `t/repo_formats.t` | audited local regression | direct repo wire-format and CAR expectations | 172 + | `t/self-service-invite-surfaces.t` | audited local regression | isolated self-service invite issuance coverage for invite minting, account scoping, and account invite-code listing | 172 173 | `t/sentry.t` | local correctness/infrastructure | Sentry event shaping, stacktrace capture, and dispatcher exception-reporting smoke | 173 174 | `t/server-auth.t` | direct reference differential | auth/session/service-auth behavior repeatedly compared to official runtime, including bounded create-session password semantics | 174 175 | `t/service-proxy-local.t` | audited local regression | local appview fallback behavior | ··· 184 185 The broadest suites are green and audited, but they still mix several categories of behavior inside the same file: 185 186 186 187 - `t/extended-api.t` 187 - Carries real conformance value for `applyWrites`, but it still mixes those with local product behavior such as self-service invite flows. 188 + Carries real conformance value for `applyWrites`, but it is now much narrower and mostly acts as a focused repo-write regression suite. 188 189 - `t/external-surface.t` 189 190 Carries strong external-surface coverage for repo export, blob access, account-status behavior, and missing-blob listing. It is cleaner after moving discovery and label-RPC checks into dedicated suites, but still remains broader than a single-endpoint conformance file. 190 191 - `t/uncovered-endpoints.t`
-21
t/extended-api.t
··· 50 50 my $access = $created->{accessJwt}; 51 51 my $did = $created->{did}; 52 52 53 - $t->post_ok('/xrpc/com.atproto.server.createInviteCode' => { 54 - Authorization => "Bearer $access", 55 - } => json => { 56 - useCount => 2, 57 - })->status_is(200) 58 - ->json_has('/code'); 59 - 60 - my $invite_code = $t->tx->res->json->{code}; 61 - 62 - $t->post_ok('/xrpc/com.atproto.server.createInviteCode' => { 63 - Authorization => "Bearer $access", 64 - } => json => { 65 - forAccount => 'did:web:example.test:users:someone-else', 66 - })->status_is(400) 67 - ->json_is('/error' => 'InvalidRequest'); 68 - 69 53 $t->post_ok('/xrpc/com.atproto.repo.createRecord' => { 70 54 Authorization => "Bearer $access", 71 55 } => json => { ··· 153 137 ], 154 138 })->status_is(400) 155 139 ->json_is('/error' => 'InvalidRequest'); 156 - 157 - $t->get_ok('/xrpc/com.atproto.server.getAccountInviteCodes' => { 158 - Authorization => "Bearer $access", 159 - })->status_is(200) 160 - ->json_is('/codes/0/code', $invite_code); 161 140 162 141 done_testing;
+73
t/self-service-invite-surfaces.t
··· 1 + use v5.34; 2 + use warnings; 3 + 4 + use Config (); 5 + use File::Spec; 6 + use File::Temp qw(tempdir); 7 + use FindBin qw($Bin); 8 + use Test::More; 9 + 10 + BEGIN { 11 + require lib; 12 + my $root = File::Spec->rel2abs(File::Spec->catdir($Bin, '..')); 13 + lib->import( 14 + File::Spec->catdir($root, 'lib'), 15 + File::Spec->catdir($root, 'local', 'lib', 'perl5'), 16 + File::Spec->catdir($root, 'local', 'lib', 'perl5', $Config::Config{archname}), 17 + ); 18 + } 19 + 20 + use Test::Mojo; 21 + use ATProto::PDS; 22 + 23 + my $root = File::Spec->rel2abs(File::Spec->catdir($Bin, '..')); 24 + my $tmp = tempdir(CLEANUP => 1); 25 + 26 + my $app = ATProto::PDS->new( 27 + project_root => $root, 28 + settings => { 29 + base_url => 'http://127.0.0.1:7755', 30 + service_handle_domain => 'example.test', 31 + service_did_method => 'did:web', 32 + jwt_secret => 'self-service-invite-secret', 33 + admin_password => 'admin-secret', 34 + self_service_invite_codes => 1, 35 + testing_auto_confirm_email => 1, 36 + data_dir => $tmp, 37 + db_path => File::Spec->catfile($tmp, 'perlsky.sqlite'), 38 + }, 39 + ); 40 + 41 + my $t = Test::Mojo->new($app); 42 + 43 + $t->post_ok('/xrpc/com.atproto.server.createAccount' => json => { 44 + handle => 'alice.example.test', 45 + email => 'alice@example.test', 46 + password => 'hunter22', 47 + })->status_is(200); 48 + 49 + my $created = $t->tx->res->json; 50 + my $access = $created->{accessJwt}; 51 + 52 + $t->post_ok('/xrpc/com.atproto.server.createInviteCode' => { 53 + Authorization => "Bearer $access", 54 + } => json => { 55 + useCount => 2, 56 + })->status_is(200) 57 + ->json_has('/code'); 58 + 59 + my $invite_code = $t->tx->res->json->{code}; 60 + 61 + $t->post_ok('/xrpc/com.atproto.server.createInviteCode' => { 62 + Authorization => "Bearer $access", 63 + } => json => { 64 + forAccount => 'did:web:example.test:users:someone-else', 65 + })->status_is(400) 66 + ->json_is('/error' => 'InvalidRequest'); 67 + 68 + $t->get_ok('/xrpc/com.atproto.server.getAccountInviteCodes' => { 69 + Authorization => "Bearer $access", 70 + })->status_is(200) 71 + ->json_is('/codes/0/code', $invite_code); 72 + 73 + done_testing;