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 local service surfaces from extended API suite

alice 8b1979f2 5eeb3d62

+73 -28
+4 -3
docs/TEST_AUDIT.md
··· 116 116 Current suite counts by bucket: 117 117 118 118 - `direct reference differential`: `5` 119 - - `audited local regression`: `33` 119 + - `audited local regression`: `34` 120 120 - `local correctness/infrastructure`: `13` 121 121 122 122 | Test file | Bucket | Current note | ··· 136 136 | `t/email-confirmation.t` | audited local regression | intentionally testing-friendly email flow plus strict missing-email and invalid-email validation semantics | 137 137 | `t/email-update-helper.t` | audited local regression | shared email-update helper normalization, token revocation, and duplicate-email error semantics | 138 138 | `t/event-stream.t` | audited local regression | wire-format, malformed frame, and event decoding coverage | 139 - | `t/extended-api.t` | audited local regression | mixes reference-aligned repo/sync/moderation happy paths with local-only surfaces such as reserved handles, temp endpoints, label fetch/query smoke, and direct `requestCrawl` exposure | 139 + | `t/extended-api.t` | audited local regression | mixes reference-aligned repo/sync/moderation happy paths with still-local label fetch/query smoke and account/invite flows, but is cleaner after splitting reserved-handle and crawl-host checks out | 140 140 | `t/external-handle-update.t` | audited local regression | external-handle update semantics, including DID-resolution checks and empty-body success for external handle adoption | 141 141 | `t/external-surface.t` | audited local regression | mixes reference-aligned repo/sync/blob/account-status behavior with local-only surfaces such as `resolveLexicon`, `checkHandleAvailability`, and `listReposByCollection`; intentionally broad, with order-insensitive label assertions rather than brittle ordering | 142 142 | `t/firehose.t` | audited local regression | repo subscription lifecycle, cursor, and CAR behavior | ··· 148 148 | `t/ipld-canonical.t` | local correctness/infrastructure | canonical IPLD encoding invariants | 149 149 | `t/ipld-codecs.t` | local correctness/infrastructure | DAG-CBOR and codec coverage | 150 150 | `t/labels.t` | audited local regression | label persistence, replay, negation, and cursor behavior | 151 + | `t/local-service-surfaces.t` | audited local regression | isolated local-only coverage for reserved handles and crawler host tracking surfaces | 151 152 | `t/metrics.t` | audited local regression | metrics endpoint, token-gating smoke, and instrumentation contract for local appview behavior | 152 153 | `t/moderation.t` | audited local regression | takedown visibility and moderation behavior | 153 154 | `t/oauth-include.t` | audited local regression | permission-set scope expansion and least-privilege enforcement from `include:<nsid>` scopes | ··· 178 179 The broadest suites are green and audited, but they still mix several categories of behavior inside the same file: 179 180 180 181 - `t/extended-api.t` 181 - Carries real conformance value for `applyWrites`, blob/sync flows, and moderation/label visibility, but it also includes clearly local-only assertions for temp endpoints, local crawler exposure, and self-service invite policy. 182 + Carries real conformance value for `applyWrites`, blob/sync flows, and moderation/label visibility, but it still mixes those with some local product behavior such as label fetch/query smoke and invite/account flows. 182 183 - `t/external-surface.t` 183 184 Carries strong external-surface coverage for repo export, blob access, and account-status behavior, but also covers local-only surfaces such as `resolveLexicon`, `checkHandleAvailability`, and `listReposByCollection`. 184 185 - `t/import-repo.t`
-25
t/extended-api.t
··· 170 170 ->json_is('/did', $did) 171 171 ->json_is('/handle', 'alice.example.test'); 172 172 173 - $t->post_ok('/xrpc/com.atproto.temp.addReservedHandle' => { 174 - Authorization => $admin_auth, 175 - } => json => { 176 - handle => 'reserved.example.test', 177 - })->status_is(200); 178 - 179 - $t->get_ok(Mojo::URL->new('/xrpc/com.atproto.temp.checkHandleAvailability')->query( 180 - handle => 'reserved.example.test', 181 - ))->status_is(200) 182 - ->json_is('/available', JSON::PP::false); 183 - 184 173 $t->post_ok('/xrpc/com.atproto.identity.updateHandle' => { 185 174 Authorization => "Bearer $access", 186 175 } => json => { ··· 316 305 _find_label($t->tx->res->json->{labels}, val => '!hide', neg => JSON::PP::true), 317 306 'fetchLabels includes the negated takedown label', 318 307 ); 319 - 320 - $t->post_ok('/xrpc/com.atproto.sync.requestCrawl' => json => { 321 - hostname => 'relay.example.test', 322 - })->status_is(200) 323 - ->content_is(q()); 324 - 325 - $t->get_ok('/xrpc/com.atproto.sync.listHosts') 326 - ->status_is(200) 327 - ->json_is('/hosts/0/hostname', 'relay.example.test'); 328 - 329 - $t->get_ok(Mojo::URL->new('/xrpc/com.atproto.sync.getHostStatus')->query( 330 - hostname => 'relay.example.test', 331 - ))->status_is(200) 332 - ->json_is('/hostname', 'relay.example.test'); 333 308 334 309 done_testing; 335 310
+69
t/local-service-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 MIME::Base64 qw(encode_base64); 9 + use Test::More; 10 + 11 + BEGIN { 12 + require lib; 13 + my $root = File::Spec->rel2abs(File::Spec->catdir($Bin, '..')); 14 + lib->import( 15 + File::Spec->catdir($root, 'lib'), 16 + File::Spec->catdir($root, 'local', 'lib', 'perl5'), 17 + File::Spec->catdir($root, 'local', 'lib', 'perl5', $Config::Config{archname}), 18 + ); 19 + } 20 + 21 + use Mojo::URL; 22 + use Test::Mojo; 23 + use ATProto::PDS; 24 + 25 + my $root = File::Spec->rel2abs(File::Spec->catdir($Bin, '..')); 26 + my $tmp = tempdir(CLEANUP => 1); 27 + 28 + my $app = ATProto::PDS->new( 29 + project_root => $root, 30 + settings => { 31 + base_url => 'http://127.0.0.1:7755', 32 + service_handle_domain => 'example.test', 33 + service_did_method => 'did:web', 34 + jwt_secret => 'local-service-surfaces-secret', 35 + admin_password => 'admin-secret', 36 + data_dir => $tmp, 37 + db_path => File::Spec->catfile($tmp, 'perlsky.sqlite'), 38 + }, 39 + ); 40 + 41 + my $t = Test::Mojo->new($app); 42 + my $admin_auth = 'Basic ' . encode_base64('admin:admin-secret', q()); 43 + 44 + $t->post_ok('/xrpc/com.atproto.temp.addReservedHandle' => { 45 + Authorization => $admin_auth, 46 + } => json => { 47 + handle => 'reserved.example.test', 48 + })->status_is(200); 49 + 50 + $t->get_ok(Mojo::URL->new('/xrpc/com.atproto.temp.checkHandleAvailability')->query( 51 + handle => 'reserved.example.test', 52 + ))->status_is(200) 53 + ->json_is('/available', JSON::PP::false); 54 + 55 + $t->post_ok('/xrpc/com.atproto.sync.requestCrawl' => json => { 56 + hostname => 'relay.example.test', 57 + })->status_is(200) 58 + ->content_is(q()); 59 + 60 + $t->get_ok('/xrpc/com.atproto.sync.listHosts') 61 + ->status_is(200) 62 + ->json_is('/hosts/0/hostname', 'relay.example.test'); 63 + 64 + $t->get_ok(Mojo::URL->new('/xrpc/com.atproto.sync.getHostStatus')->query( 65 + hostname => 'relay.example.test', 66 + ))->status_is(200) 67 + ->json_is('/hostname', 'relay.example.test'); 68 + 69 + done_testing;