-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path_index.md.old
1919 lines (1301 loc) · 137 KB
/
_index.md.old
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
name: AppFair
title: The App Fair
---
<p align="center">
<img alt="The App Fair icon" align="center" style="height: 20vh;" src="appfair-icon.svg" />
</p>
A Federated App Index Repository (FAIR) is part of a decentralized network of app stores, providing users of iPhones and other devices a choice of trusted sources for the applications and extensions they can install and use.
The App Fair ([https://appfair.net](https://appfair.net)) is one such "Fairground", and provides a set of open-source [tools](https://github.com/fair-ground/Fair.git), runtime libraries, specifications, and documentation to support this interoperable federation of trusted software repositories. The App Fair is managed by the non-profit [App Fair Project Corporation (https://appfair.org)](https://appfair.org) of Boston, Massachusetts.
Anyone can create an app for the App Fair, just as anyone can create their own App Store using the fairground tools.
### Background: The Monolithic App Store Model
The dominant commercial model for how an app gets from a developer to a consumer/user is to have a single intermediary “store” that serves as the clearinghouse for all apps that can be installed on a certain vendor's device. A user that trusts the App Store vendor (colored gold in the diagram) will thereby implicitly trust any app creator (colored orange) whose app makes it through to publication on the storefront.
```mermaid
flowchart LR
DEV((Developer\nOrganization)) -- Design\nBuild\nDocument\nTest --> PREP(Prepare\nRelease)
PREP -- Package\nRelease --> D(Tools\nIDE\nXcode)
D -- App.ipa\nmetadata --> PubAppStore[(App Store Connect\nSearch\nBrowse\nBuy\nDownload)]
PubAppStore <-- App 1.0.ipa --> AppStoreApp([App Store.app])
PubAppStore <-- App 1.1β.ipa --> TestFlight([TestFlight.app])
AppStoreApp <-.-> CONSUMER((Consumer))
TestFlight <-.-> CONSUMER
PubAppStore <-- https://appstore/UnlistedApp.ipa --> CONSUMER
PubAppStore <-- SchoolApp.ipa\nEnterpriseApp.ipa --> MDM{MDM}
MDM <-.-> CONSUMER
DEV <== Contract ==> PubAppStore
classDef untrusted fill:orange,stroke:#333,stroke-width:2px;
classDef neutral fill:skyblue,stroke:#333,stroke-width:2px;
classDef trusted fill:lightgreen,stroke:#000,stroke-width:2px;
classDef vendor fill:gold,stroke:#000,stroke-width:2px;
class DEV,e untrusted
class PREP,e untrusted
class CONSUMER,e neutral
class PubAppStore,e vendor
class TestFlight,e vendor
class AppStoreApp,e vendor
class MDM,e vendor
class D,e untrusted
```
Because the App Store vendor does not require access to the underlying source code of the apps it re-distributes, trust is only maintained through a contractual agreement between the two parties that assigns a dependent economic relationship and legal consequence to the app creator for any flagrant violations or indictments of bad behavior (such as publishing malware, virus transmission, information exfiltration, illicit tracking and spyware, exploitative behavior, etc.).
Such remediation can be effective but is unevenly applied due to subjective factors, corporate priorities, and legal obligations on the part of the App Store vendor. The result is that many applications advertised and promoted in the centralized App Stores are untrustworthy or outright malicious, while many other potentially useful apps are blocked from distribution to the public over policy or competitive differences. In addition, the App Store vendor may enact practices that are outright hostile to both the end-user as well as the app creator, such as injected advertising, tracking, and the imposition of economic rents or “taxes” on all commerce that flows through their domain.
### The Federated App Index Repository (FAIR) Model
In contrast, a “fairground” is a part of a federation of app creators and distributors who establish mutual trust by opening the source code of their apps to public scrutiny and security review.
Rather that having a contractual relationship between the Fairground and the App Creator, as with the App Store model, the Fairground instead confers trust on apps that it vends by guaranteeing that the published source code is the exact same code that was used to create the application binary that is installed on the end user's device. This prevents many classes of malware and dark patterns by ensuring that the public has the ability to review the blueprints of the apps that they trust with their personal and intimate information.
All Fairground apps are open-source, enabling the use of modern techniques and best practices such as reproducible builds, transitive source scanning, and cryptographic signatures to notarize apps as being trustworthy. Remediation of bad behavior is accomplished through the de-listing and removal of malicious applications.
```mermaid
flowchart LR
DEV((Developer\nOrganization)) -- Design\nBuild\nDocument\nTest --> PREP(Prepare\nRelease)
PREP -- Submit Merge\nPull Request --- C>Replication\nAutomation]
PREP -- Create\nRelease --- D>Build\nAutomation]
D -- App.ipa --> RELDL[(Web Site\nApp1.ipa\nDownloads)]
C -- App2.ipa ---> VERIFY{{Match\nScan\nIndex\nSign}}
RELDL <-.-> VERIFY
VERIFY -- Publish Seal\nMetadata --> PAC[(AppSource\nCatalog\nJSON)]
RELDL <-.-> AppFairApp([App Fair.app])
PAC <--> AppFairApp
AppFairApp <--> CONSUMER((Consumer))
classDef untrusted fill:orange,stroke:#333,stroke-width:2px;
classDef neutral fill:skyblue,stroke:#333,stroke-width:2px;
classDef trusted fill:lightgreen,stroke:#000,stroke-width:2px;
classDef vendor fill:gold,stroke:#000,stroke-width:2px;
class DEV,e untrusted
class PREP,e untrusted
class CONSUMER,e neutral
class PubAppStore,e vendor
class TestFlight,e vendorg
class AppStoreApp,e vendor
class MDM,e vendor
class D,e untrusted
class DEV,e untrusted
class PREP,e untrusted
class CONSUMER,e neutral
class PubAppStore,e trusted
class TestFlight,e trusted
class AppStoreApp,e trusted
class MDM,e trusted
class D,e untrusted
class VERIFY,e trusted
class C,e trusted
class PAC,e trusted
class AppFairApp,e trusted
class RELDL,e untrusted
```
### Fairground + App Store Tandem
A Fairground can operate in concert with distribution through an App Store. It has the capacity to distribute apps both directly to users (via apps that are compliant with the AppIndex JSON format, such as App Fair.app), as well as through a centralized vendor storefront such as the App Store (by mediating the submission and management of apps through a Fairground organization).
```mermaid
flowchart LR
DEV((Developer\nOrganization)) -- Design\nBuild\nDocument\nTest --> PREP(Prepare\nRelease)
PREP -- Submit Merge\nPull Request --- C>Replication\nAutomation]
PREP -- Create\nRelease --- D>Build\nAutomation]
D -- App.ipa --> RELDL[(Web Site\nApp1.ipa\nDownloads)]
C -- App2.ipa ---> VERIFY{{Match\nScan\nIndex\nSign}}
RELDL <-.-> VERIFY
RELDL <-.-> AppFairApp([App Fair.app])
VERIFY -- Publish Seal\nMetadata ---> PAC[(AppSource\nCatalog\nJSON)]
VERIFY -- Signed\nApp.ipa --> ValidatedApp{{Validate App\nfor Publication}}
PAC <--> AppFairApp
ValidatedApp -- fastlane --> PubAppStore[(App Store\nConnect)]
PubAppStore <--> AppStoreApp([App Store.app\nTestFlight.app])
AppFairApp <--> CONSUMER((Consumer))
AppStoreApp <--> CONSUMER
DEV <== Contract ==> PubAppStore
classDef untrusted fill:orange,stroke:#333,stroke-width:2px;
classDef neutral fill:skyblue,stroke:#333,stroke-width:2px;
classDef trusted fill:lightgreen,stroke:#000,stroke-width:2px;
classDef vendor fill:gold,stroke:#000,stroke-width:2px;
class DEV,e untrusted
class PREP,e untrusted
class CONSUMER,e neutral
class PubAppStore,e vendor
class TestFlight,e vendor
class AppStoreApp,e vendor
class MDM,e vendor
class D,e untrusted
class DEV,e untrusted
class PREP,e untrusted
class CONSUMER,e neutral
class PubAppStore,e trusted
class ValidatedApp,e trusted
class TestFlight,e trusted
class AppStoreApp,e trusted
class MDM,e trusted
class D,e untrusted
class VERIFY,e trusted
class C,e trusted
class PAC,e trusted
class AppFairApp,e trusted
class RELDL,e untrusted
```
By distributing to App Stores using a Fairground, developers get the best of both worlds: distribution directly to the consumer through a Fairgroup as well as re-distribution through the platform-default storefront.
## The App Fair for App Developers
App Fair apps are written in Swift and utilize a native `SwiftUI` user interface.
Apps target iOS16/macOS14 and Swift version 5.7, giving them access to modern Swift features like async/await and structured concurrency.
The distribution process for App Fair apps is instantaneous, automatic, and free.
The only requirement is a GitHub account and a willingness to share your work freely with the rest of the world.
No additional registration, sign-up, or approval is required in order to start developing and distributing apps on the App Fair.
Apps are built, validated, and distributed using GitHub's free actions for open-source projects, and so there is never any cost associated with building and distributing your apps through the App Fair.
App that are distributed through the App Fair can additionally be made available through any other channels available to the platform. For example, App Fair apps are automatically added to a `homebrew` "Cask" of apps, which enables them to be installed without the user needing to first install the App Fair catalog browser app.
<!-- ### Intro Video -->
<!--
<iframe src="https://player.vimeo.com/video/654949321?texttrack=en" frameborder="0" scrolling="no" style="width: 100%; height: 400px; min-height: 150px; border: none; overflow: hidden;" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
-->
## The App Fair fair-ground
The "fair-ground" is the name for the autonomous cataloging service that indexes the releases of forks of the base repository.
It handles organization verification, app build validation, and cataloging of all the verified apps.
The "App Fair" is the reference implementation of the fair-ground system, and is implemented as a set of GitHub repositories, workflows, and policies for cataloging the build artifacts of the app forks.
The configuration for the App Fair is defined primarily in the [appfair/App.git](https://github.com/appfair/App.git) repository, which additionally acts as the base repository to be forked by app developers.
### Introduction: the fairground process
<img align="left" width="450" alt="Diagram of the App Fair process" src="assets/fairground.svg" />
The fairground process consists of the stages of creating, developing, building, and distributing an app.
The creation, development, and release is handled by you, the developer: a fork is created from the base [`/appfair/App.git`](https://github.com/appfair/App.git) repository, and in that fork you develop your app.
Once you enable GitHub actions for your fork, your app will be automatically built and released whenever you push a semantic version tag to your fork's repository.
Since this fork is under the control of the developer, the fork is considered "untrusted", in that the app binary artifact that is built and released has no security or safety guarantees.
In order to be included in the App Fair catalog (and thus be discoverable and installable in the the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser app), the fork's release must be independently built and the results be verified as reproducible by the trusted base repository.
This process is initiated by the fork's developer, who signals their desire to validate the release by creating a pull request (PR) from the fork's `/App.git` repository back to the base `/appfair/App.git` repository.
The creation of the PR for the base `/appfair/App.git` repository will trigger the integrate process, which will verify and re-build the app's release in the trusted environment of the base fair-ground.
Verification will guarantee that the resulting app binary is signed, sandboxed, and uses the hardened runtime, and validates that the resulting built binary is identical to the version that is being released in the app's fork.
It will also verify various required metadata properties in the `appfair.xcconfig` and `Info.plist` files, such as the requirement that all security entitlements are given usage descriptions that will be communicated to end users before they can install the app.
Once verification is completed, the fork's (untrusted) release artifact will be fetched and compared with the (trusted) binary that was built by the base fair-ground.
If these binaries match, the fork's release artifact will be considered "trusted", and a cryptographic hash will be generated and published.
This hash is known as the `fairseal` for the app, and is used by the catalog browser application to ensure that any app that is to be installed has passed the verification process.
The final stage of the process is the "release", which is where the online catalog of App Fair apps is updated to include the newly built and verified forked app.
The online catalog lists the most recently verified published release artifacts for all the public forks of the base repository.
Once the fairseal has been generated for the app, it will be available for browsing and installing using the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser app)
### Fair app development
From an App developer standpoint, an App Fair app is a Swift application that is defined by a Swift Package Manager `Package.swift` file, and that uses of two source code repositories: *Fair.git* and *App.git*:
- [https://github.com/appfair/App.git](https://github.com/appfair/App.git) is the repository that is forked to create a new App Fair app; PRs submitted to this repository are automatically built and released to the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog.
- [https://github.com/fair-ground/Fair.git](https://github.com/fair-ground/Fair.git) is the runtime `SwiftUI` library that is included in every App Fair project, and acts as a sandboxed container within which your application is run. The `Fair` library is the sole required dependency for your app's `Package.swift` manifest.
## Quick Start
Anyone can create and publish their own app on the App Fair, for free, using only a web browser.
The process just requires a regular GitHub account ([signup here](https://github.com/join)) and under an hour of your time.
At the end of this Quick Start guide, you will have your own app published and available through the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser.
1. The first step is to [create a free GitHub organization](https://github.com/account/organizations/new?plan=team_free).
* The name of the organization is the name of your app, so you'll need to choose a new unique name.
* The name can be easily changed later, so just pick the first available name that comes to mind.
<img style="width: 75%; max-width: 600px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub New Organization Screen" src="assets/quickstart-new-org.png" />
2. Once you have completed the new organization process, [fork the appfair/App repository](https://github.com/appfair/App/fork) into the new organization you just created.
* The “owner” of the fork must be the new organization, rather than your personal account, since the app's name is defined by the forked repository's owner organization.
* The forked repository name must be left as "App".
* The value you enter in the Description text field will be used as the summary title in the App Fair.
<img style="width: 75%; max-width: 600px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Fork base app screen" src="assets/quickstart-fork-app.png" />
3. In your new `/App` repository fork, select the **`Settings`** tab and follow the **`Pages`** settings link on the left.
* Set the `Source` branch to be `main` and change the root folder to be `/docs`, then hit **Save**.
* This will set up the landing page for your app that can be used to publish the app description, screenshots, and support information.
<img style="width: 75%; max-width: 600px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub page settings screen" src="assets/quickstart-pages-setting.png" />
4. Select the **`Settings`** tab's **`General`** section and turn on both _`Issues`_ and _`Discussions`_ by activating their checkboxes in the `Features` area.
* These community features are required for the app to be included in the App Fair catalog.
* You can optionally enable _`Sponsorships`_ for the project.
<img style="width: 75%; max-width: 600px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub general settings screen" src="assets/quickstart-issues-discussions-setting.png" />
5. Select the **`Actions`** tab and then select the “`Configure App`” workflow on the left.
* Expand the **Run workflow** drop-down, set the version to "_0.0.1_", then hit **Run workflow**.
* Wait a couple minutes for the action to complete: the yellow dot should turn green, indicating that the workflow ran successfully.
* Common mis-configurations will be indicated by a red dot; the log for the workflow run will indicate the cause of the issue.
<img style="width: 75%; max-width: 1000px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Actions run screen" src="assets/quickstart-run-configure-app.png" />
<img style="width: 75%; max-width: 1000px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Actions run screen" src="assets/quickstart-run-configure-app-success.png" />
6. Select the **`Code`** tab and follow the _`Releases`_ link (on the right side of the page).
* Hit the **Create a new Release** button.
* Under `Choose a tag`, enter "0.0.1" and hit the "`Create new tag on publish`" menu item.
* At the bottom of the page, enable the "`This is a pre-release`" checkbox then hit the **Publish release** button.
<img style="width: 75%; max-width: 1000px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Actions run screen" src="assets/quickstart-create-release.png" />
<img style="width: 75%; max-width: 750px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Actions run screen" src="assets/quickstart-publish-release.png" />
7. Return to the **`Actions`** tab and wait for the release workflow run to complete.
* This process builds your app and releases a binary artifact.
<img style="width: 75%; max-width: 1064px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Actions run screen" src="assets/quickstart-release-action-running.png" />
<img style="width: 75%; max-width: 1100px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Actions run screen" src="assets/quickstart-release-action-success.png" />
8. Select the **`Pull Requests`** tab, then hit the **New Pull Request** button.
* On the next page, hit the **Create Pull Request** button.
* The `Title` field must be the name and version of the app (e.g., "My App Name 0.0.1"). The body can be left empty.
* Hit the **Create Pull Request** button.
<img style="width: 75%; max-width: 1020px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Pull Request screen" src="assets/quickstart-pull-request-start.png" />
<img style="width: 75%; max-width: 1017px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Pull Request screen" src="assets/quickstart-pull-request-create.png" />
9. On the new pull request page page, select the _`Checks`_ sub-tab and wait for the "_Integrate Release_" workflow run to complete successfully.
* This process creates, scans, and validates a reproducible build of your app's binary artifact in a trusted environment.
* It should take only a few minutes.
* The pull request will be automatically closed at the end of the run.
<img style="width: 75%; max-width: 1159px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Pull Request checks screen" src="assets/quickstart-pull-request-checks-start.png" />
<img style="width: 75%; max-width: 1159px; display: block; margin: 12px; border: 1px solid black;" alt="GitHub Pull Request checks screen" src="assets/quickstart-pull-request-checks-success.png" />
10. Your app will soon be listed in the [recent apps](https://www.appfair.net/fairapps-macos) catalog, indicating that it has been published successfully.
Congratulations: you now have your very own native app published on the App Fair! It just has a generic icon, and it doesn't do much of anything (since you haven't written any code yet), but it is yours to develop, maintain, and share with the world.
On a computer with macOS 12 and higher, you can now download and launch the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser, enable "Show Pre-Releases" in the app's "Fairapps" preference, search for your app name, and install and run your app. You can also share your app's landing page at `https://<your organization name>.github.io/App` to provide a link for opening your app's entry in the App Fair catalog.
<img style="width: 75%; display: block;" alt="GitHub Pull Request checks screen" src="assets/quickstart-app-entry.png" />
The next step will be to code your app, which typically involves cloning your fork to a local machine and opening `App.xcworkspace` in an IDE like `Xcode.app` to run and debug. The `App/Sources/AppContainer.swift` source file contains the scaffold for your SwiftUI code; start there to begin defining your app's behavior.
The default permissions for App Fair apps are very restrictive (no network or peripheral access, file system access restricted to the app's sandbox folder, etc.), so you can edit the `Sandbox.entitlements` file to expand the permissions for your app. This will affect the "Risk" assessment of the app as shown in the catalog browser, which plays a role in an end user's decision whether to trust and install your app.
You should also update the app's catalog description and categories by updating the repository's description and tags (e.g. "appfair-games" or "appfair-productivity"), and those changes will be automatically integrated into the App Fair catalog entry for your app.
Releasing updates to your app is simply a matter of pushing changes to your fork, updating the app version to "_0.0.2_" using the “`Configure App`” GitHub action, creating a new "_0.0.2_" release tag, and then opening a new Pull Request against [appfair/App](https://github.com/appfair/App/pulls) with your app's name and version as the title.
And for finishing touches you can fill in your `README.md` with a description of the technical aspects of your app and `docs/index.md` with your landing page's marketing copy. Screenshots saved to the `docs/screenshots/` folder will be automatically published on your landing page, and be displayed in your App Fair catalog entry the next time you publish a new release. You can also register a custom domain (using any domain name registrar) and set that domain in your fork's Pages setting, making any changes your push from your `docs/` folder immediately available as your app's home page.
Continue reading for the full development guide, FAQs, and discussion of the security and source disclosure mechanisms for fair-ground apps. Jump right in and start developing your own native app!
## The Structure of an App Fair app
### App Organization
Your App's name is represented uniquely by a GitHub Organization, so the first step is to [create a new free organization](https://github.com/account/organizations/new).
The App's organization name must be one or more words consisting of 3-12 letters from the Roman alphabet in upper or lower case (A–Z, a–z), with multiple words separated by a hyphen (e.g., "App-Fair").
For example, the GitHub organization for the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser application itself is [https://github.com/App-Fair/](https://github.com/App-Fair/).
Your app organization can be structured however you want, and can consist of a team of as few or as many as you like.
You can manage, create and distribute multiple apps by creating multiple separate uniquely-named organizations.
Each organization will have a single top-level `/App.git` fork that acts as the repository for your app's development and uses pull requests as the communication link to the reproduction process.
There can be only a single `/App.git` repository per organization.
### App Repository
Once your organization is set up, you create your `/App-Name/App.git` project by forking the [https://github.com/appfair/App.git](https://github.com/appfair/App.git) repository into your new organization name.
This is a Swift project that contains the shell of a cross-platform `SwiftUI` app that you will use as your starting point.
Your app will exist in a top-level repository named "App"; it must continue to be called "App" since that is how the catalog browser will be able to access your project metadata.
For more information on the fork process, see [Working with forks](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks).
<!--
XXX ### Developing with an IDE
XXX ### Parts included in integration
XXX ### Developing as a Swift package
XXX ### Handling Versioning
I-R requires increasing build number and semantic version.
XXX ### Translating and Localizing your App
-->
<a name="App.yml"/>
## App.yml Metadata
The core metadata for your app is stored in the `App.yml` file at the
root of your App.git fork. This is a YAML text file that will be
used at build-time and deploy-time to describe your app.
### Developing your `/App-Name/App.git` fork
The `/App-Name/App.git` repository is structured as a standard Swift package and includes the following code that must be included as the scaffold and starting point for your app:
* `Package.swift`
* `Sources/App/AppContainer.swift`
* `Tests/AppTests/AppTests.swift`
In addition, at the top level of the repository, there are `Xcode`-specific project files that describe the metadata, build rules, assets, and permissions for the project:
* `App.yml` – The localizable description and metadata for your app
* `App.xcworkspace` – Xcode workspace file for running and debugging your app
* `appfair.xcconfig` – build-time metadata about your app containing the name, version and build numbers
* `project.xcodeproj` – internal project file; you should not open this directly, but instead work with `App.xcworkspace`
* `Info.plist` – runtime metadata about your app containing the information about what files and URL schemes it can handle
* `sandbox-<platform>.entitlements` – permissions that should be granted to your app
* `Assets.xcassets` – the app's icon and tint color definition (auto-generated when left un-configured)
App development should be done by opening `App.xcworkspace` using `Xcode.app` to build, run, and debug the `SwiftUI` app that is defined in `Sources/App/AppContainer.swift`.
Note, however, that changes to these project files, `App.xcworkspace` and `project.xcodeproj`, will *not* be incorporated into the final project.
It will be best not to make changes to the project files themselves, since none of the changes will be used in the eventual reproduction stages of the process.
Specifically, your build must not rely on any script build stages that you add to the project files since these scripts will not be run during `I-R`.
When adding project files, they should be added directly to the `App` Swift package's `Sources/App/` folder or a sub-folder that you create.
These source files will automatically be incorporated into the Xcode project, so there is no need to add the sources files to the project itself; doing so may result in built errors.
Localizable resources (such as `.strings` files containing translations of your app into different languages) should be placed beneath `Sources/App/Resources/`, which is the folder that will be pre-processed and flattened as part of the build process.
Resource files that need to retain their directory structure should be instead placed in the `Sources/App/Bundle/`.
These resource bundles will be available at runtime by referencing the `Foundation.Bundle.module` accessor, and then using standard `Bundle` API to load resources and localize strings.
### Managing dependencies in your `/App-Name/App.git` fork
The `Package.swift` file that defines how your package is built.
You can add anything your want to your `Package.swift` manifest, but note that the fair-grounds validation process has some requirements:
1. The *initial* dependency for your package must be the `Fair.git` project's `main` branch, and this project must appear as the first dependency for the `App` target
1. The `App` target name must remain unchanged.
This restriction is enforced by the `Integration` stage of the process, which will refuse to build the project if the `Package.swift` manifest is invalid.
You can preview this validation with your own project by replacing `App-Name` with your app name, installing the [fairtool](#fairtool), and running:
```shell
fairtool fair validate --verbose true --hub github.com/appfair --org App-Name --project .
```
If you create a read-only GitHub developer token, you can perform further validations (like verifying that the repository issues and discussions are properly set up) by adding the `--token` flag:
```shell
fairtool fair validate --verbose true --hub github.com/appfair --org App-Name --project . --token GH_TOKEN
```
### AppContainer.swift and AppMain.swift
The `Sources/App/AppMain.swift` is the entry point to your app on all available platforms.
The contents of the file must not be changed; otherwise, validation of your project will fail at the reproduction stage.
To customize your app, you should instead start by editing the `AppContainer` extension in `Sources/App/AppContainer.swift` to provide the required protocol implementations for your app's root view.
### The Fair Library
The [fair-ground/Fair](https://github.com/fair-ground/Fair.git) repository is the cornerstone for the App Fair.
Fair contains the code for the following aspects of a fair-ground:
1. Managing the fair-ground process (app validation and catalog management) using the `fairtool` executable target running on the fair-ground's build host
1. Serving as the canonical source for the contents of the fair-ground's base repository, such as the App Fair's at: [https://github.com/appfair/App.git](https://github.com/appfair/App.git)
1. Acting as the point of entry to an app's launch, thereby providing automatic runtime features such as integration with the fair-ground's catalog management and runtime security checks
All apps distributed through a fair-ground such as the App Fair must include the HEAD of the `Fair` library as their initial dependency.
This ensures that all integrated apps are always up-to-date with respect to feature improvements, bug fixes, and security enhancements that may be made to the container environment.
This requirement is enforced during the reproduction and validation stages.
## fairtool
The `fairtool` is the name of the cross-platform command line interface tool that is included with the `Fair` project which is used to validate a project, generate icons, and generate the [app source](#appsource) catalog.
It is primarily used by the GitHub action workflows that handle the integration-release stages of the process.
[Homebrew](https://brew.sh) users on macOS and Linux can run the fairtool
command locally with the `Terminal.app` command:
```
brew install fair-ground/tool/fairtool
```
You can check your installation with the commands:
```
fairtool version
fairtool --help
```
More information on the `fairtool` can be found in the documentation at
[fair-ground/Fair](https://github.com/fair-ground/Fair).
An online version of the `fairtool` that can perform a limited subset of the tool commands
is available at [https://fairtool.herokuapp.com](https://fairtool.herokuapp.com).
### The SPM Package.swift manifest
All the source code for your applications much either reside in the `Sources/` folder, or else be accessible from any dependencies you add to the `Swift.package` manifest.
A typical manifest for an app will look like this:
```
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "App",
defaultLocalization: "en",
platforms: [ .macOS(.v12), .iOS(.v15) ],
products: [ .library(name: "App", targets: ["App"]) ],
dependencies: [
// the Fair main branch must be the first dependency to pass integration
.package(name: "Fair", url: "https://github.com/fair-ground/Fair", .branch("main")),
// additional GitHub-hosted dependencies can be added below
],
targets: [
.target(name: "App", dependencies: [ .product(name: "FairApp", package: "Fair") ], resources: [.process("Resources"), .copy("Bundle")]),
.testTarget(name: "AppTests", dependencies: ["App"]),
]
)
```
This is a standard [Swift Package Manager manifest](https://swift.org/package-manager/) with the following additional requirements:
1. The `App` target name must remain unchanged.
1. the *initial* dependency for your package must be the `https://github.com/fair-ground/Fair.git` project's `main` branch, and this project must appear as the first dependency for the `App` target
### The App Fair sandbox
The "sandbox" is the name for a security environment within which a program is run that restricts the capabilities of the software.
Your `/App-Name/App.git` fork is pre-configured to request minimal permissions, and thus runs in a very restrictive sandboxed environment: USB and bluetooth hardware access is not permitted, network access communication is blocked, and file access outside the app's own sandboxed container is not allowed.
You may add new entitlements to your `/App-Name/App.git` fork's `Sandbox.entitlements` file.
For each entitlement that is requested, a description of the reason for the entitlement must be added to a `FairUsage` dictionary in the `Info.plist`.
The description's key should be the same as the key of the entitlement.
For an example, see the base [Info.plist](https://github.com/appfair/App/blob/main/Info.plist) file.
The presence of the `FairUsage` key is enforced by the `Integration` stage.
These descriptions should be plain language explaining why the app needs access to the specific permissions.
The descriptions will be presented to the user via the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser, and the user will need to confirm that the app should be granted these permissions.
The apps may periodically remind the users of the permissions that have been granted to the app, and re-confirm with the user whether the app may continue to be granted the permissions.
This is in addition to automatic confirmations and re-confirmations that the host OS may present to the user over time.
For these reasons, you should not request permissions that your app does not need.
The fewer entitlements the app is granted, the safer the app will appear to be to users, and they are more likely to trust and install your app.
For example, if you are making a stand-alone utility or game, you will often not need any entitlements at all.
## Continuous Integration
The built-in `fairground.yml` workflow can automatically build your app in the cloud, eliminating the need for dedicated build infrastructure.
Since GitHub Actions are free for open-source repositories, your `/App.git` fork will be able to verify that every commit continues to create a build-able and tested application.
Once the developer enables the `Actions` for their `/App.git` fork, the GitHub workflow defined in the `.github/workflows/fairground.yml` file of the fork will become active.
The workflow will build and test your app every time you commit to the `main` branch.
You should avoid customizing the `fairground.yml` workflow itself, since that file may be verified during `I-R`.
## Creating Releases
In addition, if you commit a tag with a semantic version that matches the version in your `appfair.xcconfig`'s `MARKETING_VERSION` property, a release will be created with the build's artifacts, and will become available in your app's `/releases` root.
The developer has complete control over their app's own releases, and they can add, remove, hide, or mark as drafts or pre-releases any release in any of their forks.
### Release Artifacts
The `/App.git` fork's `/releases` page contain all the releases of the app that will be available to the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser.
The artifacts contain the application binaries that will be installed on the end-user's device.
The release artifacts also include a number of other metadata related to the app:
* `App-Name.png`: the app's icon
* `App-Name-macOS.zip`: the macOS application packaged in a zip file
* `App-Name-iOS.ipa`: the iOS application packaged in a zip file
* `App-Name-macOS.plist`: the metadata about the macOS application, such as the title, version, and entitlement descriptions
* `App-Name-iOS.plist`: the metadata about the iOS application
* `Sandbox.entitlements`: the list of permissions the app will request, such as network or file system access
* `App-Name-source.tgz`: the complete source code of the integration PR as well as all the resolved SPM dependencies that were used to create the release
* `Package.resolved`: the release versions of all the resolved SPM dependencies
(Note that in addition to these artifacts, GitHub also automatically includes a "Source code (zip)" and "Source code (tar.gz)" archive in the releases; these are 'shallow' source archives without any resolved dependencies and so it not a complete archive of all the code that was used to build the app. This is why the generated `App-Name-source.tgz` release artifact is generated).
## Integration-Release pull requests
Once a [release](#creating-releases) has been successfully created and publicly available, it becomes eligible for inclusion in the App Fair's catalog.
The mechanism by which app releases (both the initial release, as well as subsequent updates) are communicated to the cataloging process by opening (or re-opening) a pull request from the developer's `/App.git` fork.
This PR will not ever be merged in the base repository; rather, it acts as a trigger to initiate the `Integration` and `Releases` stages of the App Fair process, and as a mechanism for tracking the status of the catalog request.
The Pull Request is always closed at the end of the `Integration-Release` workflow run regardless of success.
The cataloging process, which is run with the permissions in the base `/App.git` repository, checks out the fork's PR changes.
After validating that the organization is valid (issues and discussions enabled, etc) and that the secure portions of the project (e.g., the `project.xcodeproj` and `Sources/App/AppMain.swift` files) haven't been tampered with, it will build the project using the Swift Package Manager's sandboxed build system.
If the app passes validation and is built successfully, the resulting release artifacts are then compared to the release artifacts that were built and released in the `/App.git`'s forked repository.
If these release artifacts match the artifacts from the `/App.git`'s forked repository's release, then the fork's artifacts will be considered "trusted", and the base fair-ground will publish the `fairseal` (a SHA-256 hash of the fork's validated release artifact) for that fork's release, thereby making it eligible for inclusion in the fair-ground's catalog.
The <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser will validate that any app that it downloads has a valid `fairseal`, which demonstrates that the app that was downloaded is exactly the same as the app that passed the validation process.
Once this process has been completed for an initial release of the app, the pull request can either be closed or left open.
The decision of which to do is up to the developer, and the choice has the following effects:
### Keeping Open the Integration-Release PR
If the Integration-Release pull request is left open after a tagged release has passed integration, the PR will continue to be automatically updated whenever commits are pushed to the branch that opened the PR.
This means that every time a commit is pushed, a new release process will be attempted, so you should only commit to the PR's branch when a release is ready to be made.
### Closing the Integration-Release PR
Closing the Integration-Release PR will have no effect once the release has been validated and the `fairseal`s for the release artifacts has been published.
Once the developer is ready to create another new release, they can simply open a new PR with their changes for the new release and the `Integration-Release` process will begin anew for the new release.
### Following the status of the Integration-Release request
Once the Integration-Release PR has been created, you will see a status update at the bottom of the PR:
```
"Reproduction and Validation" (pull_request_target) In progress — This check has started... (Details)
```
Clicking the `details` link will show a live log of the `Integration-Release` process for the base `/App.git` repository.
If `I-R` fails, you can reference these action logs to see the error that may have occurred.
Most frequently, failure is a result of either a configuration problem (e.g., discussions or issues not being enabled), or a formatting issue (e.g., appfair.xcconfig's `MARKETING_VERSION` version not matching the current release tag), or else simply a build error.
Errors with the `fairseal` process can be more challenging to debug, because validation will fail if there is *any* difference between the fork's release artifacts and those artifacts that were generated by the trusted fair-ground's validation process.
The fair-ground system relies on build artifacts being exactly (byte-by-byte) reproducible, as this is how the system ensures that the untrusted fork's release artifacts conform to the structure and security, disclosure, and sandboxing rules imposed by the fair-ground.
## App Customization
### App Category
App categorization is done using GitHub topics.
The various pre-existing topics ("appfair-games", "appfair-utilities", etc.) are used for specifying the category that the app will show up under.
These tags must be mirrored in the `APP_CATEGORY` property of your app's `appfair.xcconfig` file, with the "appfair-" prefix being renamed to "public.app-category.".
For example, the "appfair-games" GitHub topic should be represented using the "public.app-category.games" value for the `APP_CATEGORY`.
A mis-match between the GitHub topic name and the `APP_CATEGORY` setting for the most recent release build will cause the app to be excluded from the catalog.
Since changing the category requires the issuing of a new release, changing the GitHub topic should be timed to happen before the initiation of the reproduction pull request.
### App Icons & Colors
There are no icons in the default `/App.git` fork.
During the release stage of the fair-ground, icons will be automatically generated with the App's monogram and a color unique to that app's name.
This provides the app with a minimal icon that is sufficient to distinguish the app from other un-customized apps.
The generated icons will not be part of any local builds of the app, but they will be created and injected with the app's release build occurs.
The auto-generation process can be customized using the following keys in the `appfair.xcconfig` file:
* `ICON_TINT`: a 6-character RGB hex string that will be used as the base color for the generated icon; if this is excluded, the tint of the icon will be derived from the app's tint color defined in `Assets.xcassets/AccentColor.colorset/Contents.json`
* `ICON_SYMBOL`: a system symbol name or SVG path string to embed in the icon instead of the default monogram of the app's name; when using a symbol name, it must be available on the build machine that performs the app release (which means that symbols new in macOS 12 won't render anything on macOS 11 build hosts).
### Using a custom app icon
It is expected that many apps will want to create their own bespoke icon rather than relying on the auto-generated icon.
The `Assets.xcassets/AppIcon.appiconset` is a standard asset catalog, and any custom icons added to this asset catalog will not be overwritten by the default icon generation for the app.
The auto-generate icon names will be generated with the following filenames, which match the idiom and sizes of the require minimal set of icons:
```
appicon-mac-16x16@2x.png
appicon-mac-128x128@2x.png
appicon-mac-256x256@2x.png
appicon-mac-512x512@2x.png
appicon-ipad-76x76@1x.png
appicon-ipad-76x76@2x.png
appicon-ipad-83.5x83.5@2x.png
appicon-iphone-60x60@2x.png
appicon-iphone-60x60@3x.png
appicon-ios-marketing-1024x1024@1x.png
```
If these files are added to the `Assets.xcassets/AppIcon.appiconset/` asset catalog with custom icons at the appropriate sizes, they will be used by the fair-ground instead of the auto-generated icons.
### App Screenshots
Screenshots for your app that are saved to your `docs/screenshots/` folder will be automatically included in both the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog entry for the app, as well as your app's landing page at `https://<your organization name>.github.io/App`.
Screenshots should be named: `screenshot_[01]-[device]-[mode]-[width]x[height]@[scale].png`, where `[device]` is `mac`, `iphone`, or `ipad` and `[mode]` is either `light` or `dark`. The width and height are not constrained, so you can display any shape of window.
If two screenshots are named the same thing with only the exception of the `mode` part, they will be assumed to be a shot of the exact same screen (varying only between dark and light modes), and may be given special treatment by the catalog browser app. For example:
* `screenshot_04-iphone-dark-828x1792.png`
* `screenshot_04-iphone-light-828x1792.png`
# The App Fair Catalog
## App Fair Catalog Requirements
The "App Fair" catalog is the list of validated app releases, cross-referenced with the metadata for the `/App.git` forks: issues, discussions, support info, wikis, project web site, etc.
The catalog is automatically re-generated after each successful reproduction and validation stages, and it is also periodically refreshed to re-validate the forks and ensure that only valid entries are included in the list of installable apps.
### Org Requirements
In order for an organization's `/App-Name/App.git` project to be visible in the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog, it must be a public organization with at least one public member.
The organization must have a repository (or redirection) named "App" (literally), which must be a fork of the [appfair/App.git](https://github.com/appfair/App.git) repository.
In addition, the repository must have issues and discussions enabled, and also must be public and un-archived.
Finally, the `App-Name` organization's public contact must be a valid e-mail address associated with the GitHub user that creates releases for the project.
## Catalog Formats
<a name="appsource"/>
## App Source Catalog
An AppSource catalog is a JSON file that lists the apps available in a collection.
This catalog format is designed to provide interoperable metadata about an
app, including its name, download location, size, and optional metadata
such as screenshots and localized versions of the strings.
The JSON Schema for the appsource catalog format can be found at
[https://appfair.net/appsource-schema.json](https://appfair.net/appsource-schema.json).
This schema can be used to check the validity of
exiting catalogs.
#### App Source Example
An example of an app source catalog with a single app is as follows:
```json
{
"name": "A Simple App Source Catalog",
"identifier": "net.example.catalog",
"platform": "macos",
"sourceURL": "https://catalog.example.net/apps.json",
"iconURL": "https://catalog.example.net/catalog.png",
"tintColor": "RGBHEX",
"localizedDescription": "This is a **great** catalog of apps!",
"apps": [
{
"name": "App Name",
"subtitle": "A brief 30char app description",
"localizedDescription": "A longer (max 1000 char) description of the app. Limited markdown permitted.",
"developerName": "Developer Name <developer@example.net>",
"bundleIdentifier": "net.example.bundle.identifier.from.info.plist",
"iconURL": "https://app.example.net/assets/app-icon_512x512.png",
"tintColor": "RGBHEX",
"version": "1.8.1",
"versionDate": "2022-03-12T10:31:59Z",
"versionDescription": "A description (max 1000 char) of what has changed in this release. Limited markdown permitted.",
"downloadURL": "https://app.example.net/releases/download/1.8.1/app-archive.ipa",
"sha256": "74247c3e_sha_256_checksum_of_downloadURL_8a3b671143404681da26b96f",
"size": 3503022,
"screenshotURLs": [
"https://app.example.net/releases/download/1.8.1/screenshot_01-iphone-light-750x1334.png",
"https://app.example.net/releases/download/1.8.1/screenshot_02-iphone-dark-750x1334.png"
],
"permissions": [
{
"type": "usage",
"identifier": "NSBluetoothPeripheralUsageDescription",
"usageDescription": "Attestation of this app's bluetooth peripheral usage purpose."
},
{
"type": "usage",
"identifier": "NSLocalNetworkUsageDescription",
"usageDescription": "Attestation of this app's local network usage purpose."
},
{
"type": "background-mode",
"identifier": "audio",
"usageDescription": "Attestation of this app's audio background mode purpose."
},
{
"type": "entitlement",
"identifier": "com.vendor.developer.networking.multicast",
"usageDescription": "Attestation of this app's multicast entitlement purpose."
}
],
"localizations": {
"fr-FR": {
"name": "Le Nom d'App",
"subtitle": "Une app fantastique!",
}
}
}
]
}
```
#### App Catalog Properties
The top level catalog contains the following properties:
- `name`: A localized name for the catalog (e.g., "A Simple App Source Catalog"). Required.
- `identifier`: A unique identifier for the catalog in reverse DNS notation (e.g., "org.example.catalog"). Required.
- `platform`: The name of the platform for the catalog, such as `macos`, `ios`, or `android`. If left blank, the platform may be inferred by a client application. Optional.
- `localizedDescription`: A description of this catalog. Supports limited markdown (e.g., bold and italics). Optional.
- `homepage`: The home page for the catalog. Optional.
- `sourceURL`: The canonical link to this catalog. Optional.
- `iconURL`: A link to a small .png image for the catalog. Optional.
- `tintColor`: An RGB hex color string for suggested styling; this should typically match the dominant color from the catalog's icon. Optional.
- `apps`: An array of the apps that are available from this app source catalog. Required.
#### App Source Properties
An element of the "apps" array will contain the following properties:
- `name`: The name of the app. Must match the value of the `CFBundleName` property in the `Info.plist` file.
- `subtitle`: A single-line concisely (80 char limit) describing what the app does. Required.
- `localizedDescription`: A description of this app. Supports limited markdown (e.g., bold and italics). Required.
- `developerName`: The name and e-mail address of the primary developer of the app, in the form `Developer Name <developer@email.address>`. Required.
- `bundleIdentifier`: The value of the `CFBundleIdentifier` property in the `Info.plist` file. Required.
- `iconURL`: A URL for a 512x512 `.png` icon for the app. Required.
- `tintColor`: An RGB hex color string for suggested styling for the app; this should typically match the dominant color from the icon. Optional.
- `version`: The semantic version string for this version of the app. Must match the value of the `CFBundleShortVersionString` property in the `Info.plist`. Required.
- `versionDate`: An ISO-8601 date string for this version of the app. Required.
- `versionDescription`: A description of the changes made to this version of the app. Required.
- `downloadURL`: The URL of the `.ipa` or `.zip` archive of the app. Required.
- `sha256`: The SHA256 checksum of the contents of the `downloadURL`. Optional, but may be required by client applications.
- `size`: The size, in bytes, of the contents of the `downloadURL`. Optional, but may be required by client applications.
- `screenshotURLs`: An array of URL strings pointing to a PNG screenshot of the app. Optional.
- `permissions`: An array of permission definitions, one for each entitlement, background mode, and feature `*UsageDescription` in use by the app. Optional only if there are no permissions, entitlements, or background modes used by the app. See [Permission Types](#permission-types).
- `localizations`: An object with keys as languages named ("en-US", "fr-FR", etc.) and whose values contain the same app item as the container, but with localized string values.
#### Permission Types
The properties of the elements of the `permissions` array will vary depending on what `type`
of permission it describes.
- `type`: one of the supported permission classes, such as `usage`, `entitlement`, or `background-mode`.
- `identifier`: this property will vary depending on the value of the `identifier` property:
- `usage`: the `identifier` will be one of the standard usage descriptions. E.g., `NSBluetoothPeripheralUsageDescription`.
- `background-mode`: the `identifier` will be one of the background modes. E.g., `audio`
- `entitlement`: the `identifier` will be the key of the entitielement. E.g., `keychain-access-groups` or `com.vendor.entitlement.id`
- `usageDescription`: the localized attestation of the reason the app may need to use the permission.
### Catalog Generation
The catalog is automatically constructed from the list of all the [forks of the appfair/App.git](https://github.com/appfair/App/network/members) who have passed the reproduction and validation stages and have a released artifact, and whose organizations are valid (e.g., have a valid app name and have issues and discussions enabled).
The [fairtool](#fairtool) `fair catalog` command is used to generate the catalog using the GitHub GraphQL API.
### Homebrew Cask
In addition to the JSON catalog format used by <a href="https://appfair.app" target="_blank">`App Fair.app`</a>, a "Cask" for each app is generated and pushed to [https://github.com/appfair/homebrew-app/tree/main/Casks](https://github.com/appfair/homebrew-app/tree/main/Casks).
This enables any app to be installed (and un-installed) using the [homebrew](https://brew.sh) package manager using the following and replacing "app-name" with the lower-case hyphen-separated name of your app:
```shell
$ brew install appfair/app/app-name
```
Pre-release versions of apps can also be installed with the `-prerelease` suffix:
```shell
$ brew install appfair/app/app-name-prerelease
```
Apps installed using `brew install` are placed in the same
`App Fair` sub-folder of the `Applications` folder, and
can continue to be managed by the App Fair catalog browser.
:exclamation: Note that <a href="https://appfair.app" target="_blank">`App Fair.app`</a> does not use the
system-wide Homebrew database, so apps added or removed will not be
tracked by Homebrew, which may result in `brew upgrade`
becoming confused if apps it installs are then upgraded
by the <a href="https://appfair.app" target="_blank">`App Fair.app`</a>.
In addition, switching between stable and pre-release
versions of apps will require first un-installing
the alternate version, since `Homebrew` will not know
that the two different forms of the app are related.
Issues between Homebrew and <a href="https://appfair.app" target="_blank">`App Fair.app`</a>
can often be mitigated with the `--force` flag to the `brew command`.
<!--
# Principles of the App Fair
The App Fair is founded on a principle of mutual respect between the software users and the developers of the software.
## Ideal: Free
App Fair apps are always free; there is never any cost to download and install apps from the catalog, nor is there any mechanism for in-app purchases or subscriptions.
All apps on the App Fair are licensed under the [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html), thereby guaranteeing that they will be free and fair, forever.
In addition, software creators benefit from the creative freedom afforded by a platform with no annual corporate developer fees, capricious gate-keeping, or periodic acquiescence to perpetually-fluctuating terms and conditions.
Since apps developed for the App Fair are distributed directly from the GitHub fork controlled by the developer, the developer maintains exclusive control over how their app is distributed.
## Ideal: Fair
A fair-ground is a nexus that enables both *sovereignty* for software creators and *agency* for software consumers.
The App Fair is designed to encourage fairness and respect between software creators (the app developers) and software consumers (the users of the app).
This relationship is mediated by fair-ground distribution platforms such as the App Fair.
Software creators benefit from a fair platform without the delays and uncertainly of an opaque app review process.
They also benefit from the global reach of a centralized and self-maintaining catalog with the unfettered ability to distribute bug fixes and feature improvements to their users in real time.
In exchange for access to this distribution platform and audience, they commit to publishing all their source code for other developers to scrutinize, improve, and share.
Software consumers benefit from a large catalog of truly free software without any hidden undesired behaviors.
The [Source Accountability](#source-accountability) feature of the App Fair ensures that a user of the software knows the identity of the creator and has open channels to contact the developer for support.
Consumers additionally benefit from the confidence that the apps they rely upon are not subject to a mercurial set of rules that may affect their ongoing availability in a catalog.
### Creator-Platform-Consumer Trust Relationship
Any system of software aggregation and distribution involves three groups:
- Consumers: the end-users of the software. These are the people that use the Platform to find, research, install, and update software on the devices.
- Creators: the person or people that develop the software designed to be distributed to Consumers via the Platform.
- Platform: the software processes that handle the ingestion, validation, packaging, cataloging, rating, and distribution of software from Creators to Consumers.
The guiding principles for each relationship pair is:
- Creator-Platform: the Creator trusts the distribution platform to treat them fairly. A creator should not be advantaged or disadvantaged by hidden rules implemented by the Platform. Creators should have free and unfettered control over how they add, remove, or update apps available in the Platform's catalog.
- Consumer-Platform: the Consumer trusts that the Platform will provide a safe and reliable mechanism to find, research, install, and update software. The Consumers rely on the Platform to ensure that there are public and accountable communication channels available for the Consumer to relay questions and concerns to the Creator.
– Consumer-Creator: the Consumer trusts that the Creator has provided their app in good-faith and has disclosed all the details about the capabilities of the app and any inherent dangers associated with using the app. The Consumer must be confident that the Platform is validating, to the extent possible through automation, that the Creator's product works as designed and does not embed hidden or unwanted functionality that is orthogonal to the claimed benefits of the app.
## Ideal: Forever
While apps distributed via the App Fair catalog can be removed by their creators at any time, the apps do not otherwise expire.
Once you have downloaded and installed an app, you can be confident that it will remain in its current operational state until you remove or update it.
To this end, the App Fair does not impose any automatic updating mechanism on your apps.
App updates must always be explicitly initiated by the end user.
-->
## App Fair Security
A challenge for any application distribution platform is dealing with "badware", which can be simply defined as software with undesired effects.
These can be merely annoying and wasteful, such as adware, containers for offensive content, covert proof-of-work crypto-currency miners, and other potentially unwanted programs ("PUPs").
Software can also be actively hostile, such as programs that attempt to exfiltrate your personal data and activities ("spyware") or programs that attempt to lock you out of your own data ("ransomware").
At the extreme end of the spectrum, programs that run on your computer can be actively dangerous both to you and to the broader network: they can act as hosts for virus propagation or externally-coordinated clients for a "botnet" that can perform distributed denial of service (DDoS) attacks or other malicious activities.
Web browsers have been dealing with these risks and issues ever since the web was born.
Browsers have evolved to enable arbitrary code to be run while still protecting the user's system and privacy (to some extent) by having the untrusted code run inside a sandbox that restricts the sorts of activities that are permitted: file system access is generally restricted to cookie storage and compartmentalized local file storage APIs, and network access is typically limited to HTTP and websocket access back to the network host for the page that loaded the code.
Similarly, applications that run on most modern operating systems can be "hardened" and constrained to running in a "sandbox", which restricts the application in what it can see and do.
File system access, including access to your personal data (such as contacts, mail, and photos), require explicit consent from the user before the app can access the data.
Similarly, direct access to the local hardware (microphone, video/camera, keyboard) is constrained and also requires explicit consent.
The App Fair integration process requires that all software be hardened and sandboxed in order to be visible in, and installable from, the catalog.
### Source Transparency
The App Fair's reproduction and validation build process is automatic; there is no individual review of apps when they are initially submitted, nor is there any manual review process for update releases.
This allows the release and update processes to be free of delays and keeps the catalog unencumbered by the subjective judgements of human reviewers.
It also precludes the possibility of any pre-distribution "gate-keeping" to enforce content or policy.
The App Fair instead provides post-distribution accountability by requiring that the source code for the entire app be available to the build process and that it be hosted in publicly-available forks of the base GitHub repository.
For any release in the App Fair catalog, the complete source code is available for inspection, review, and analysis by the entire world.
This access enables the security community to use all its resources to identify, isolate, and mitigate badly-behaved apps.
In addition, a requirement that all the code be hosted in publicly-available Git repositories means that tools like [code scanning](https://docs.github.com/en/code-security/secure-coding/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning) can be used to identify security vulnerabilities in the app or any of the frameworks it embeds.
### Source Accountability
The App Fair's build process signs the release's binary artifacts with an ad-hoc code signing certificate.
While this satisfies the policy requirements of certain platforms and provides some protection against tampering, this ad-hoc signature itself does not confer any useful identifying information.
The signature is essentially an anonymous seal on the binary placed on it by the reproduction and validation build stages.
Instead, the App Fair provides author accountability and identifiability by requiring that any commit that triggers the reproduction and validation workflow needs to be marked as `verified` by GitHub.
This means that the commit itself is cryptographically signed.
This signature must be associated with a public e-mail address, and that address must be associated with the developer's GitHub account.
The address does not need to be the primary address for the user, but it does need to be listed in the developer's validated public e-mail addresses at [https://github.com/settings/profile](https://github.com/settings/profile).
The simplest way to sign your PR commit is to simply use the GitHub web interface whenever you update your PR to trigger the reproduction and validation stages.
GitHub will mark any commit that you make using their web interface as being "verified" with whichever of the e-mail addresses you have configured with them.
Alternatively, you can sign commits from the `Terminal.app` using the `gpg` tool, which you can install using `homebrew`.
This will enable you to update your PR from the terminal, but is considerably more complex to set up.
For information on setting up commit signing, see the following documentation:
* [Signing commits](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification/signing-commits)
* [Telling git about your signing key](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification/telling-git-about-your-signing-key)
* [Associating an email with your GPG key](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification/associating-an-email-with-your-gpg-key)
* [Setting your commit email address](https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/managing-email-preferences/setting-your-commit-email-address)
Note that only the commit that creates or updates the reproduction PR is required to be signed.
Commits to the fork's repository itself, or to any third-party dependency repositories, do not need to be signed (although it is always encouraged).
For this reason, it is the creator of the PR's commit that is considered to be the "author" of the app in terms of validation and accountability.
### Release Artifact Scanning
In addition to protections that may be provided by GitHub's own source and binary artifact scanning, the reproduction and validation stages performs virus and malware scanning on released artifacts before it will issue a `fairseal`.
This provides an additional pre-publication line of defense against any malicious payloads that may manage to get bundled in with the release artifacts.
Along with these preventative layers of protection, macOS itself provides multiple independent remedial protections against malicious binaries:
* built-in antivirus technology called "XProtect" performs signature-based detection of malware using a database that is updated regularly with signatures of newly-identified malware infections and strains
* the "Malware Removal Tool" (MRT) process remediates infections based on automatic updates of system data files and security information. The MRT removes malware upon receiving updated information, and it continues to check for infections on restart and login.
## The macOS App
The App Fair app catalog can be accessed using `App Fair.app`, which is a native app for macOS 12.5 that can be downloaded from [appfair.app](https://appfair.app).
New users should start by downloading this app and exploring its features and capabilities.
For help and assistance with the App Fair application itself,
visit the [project discussions](https://github.com/App-Fair/App/discussions),
join the [discord channel](https://discord.gg/R4bFP8qpw7),
and browse the [issue reports](https://github.com/App-Fair/App/issues).
The rest of this document serves as a guide for the development and publication of your own apps on the appfair.net [app source](#appsource) catalog;
It assumes some familiarity with GitHub and software development in the Swift programming language.
## The App Fair for End Users
<a href="assets/app-fair-app.png" target="_blank"><img align="right" width="50%" alt="App Fair macOS Catalog Browser App" src="assets/app-fair-app.png" /></a>
From an end-user perspective, the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser is a graphical tool that enables users to search, browse, compare, appraise, install, and update apps from an unlimited online collection of free and open-source applications.
Apps installed through the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> application are built using the platform-native `SwiftUI` framework and compiled for both Intel and ARM processors, thereby enabling higher performance, lower memory consumption, and more efficient resource utilization than can be achieved with non-native cross-platform application frameworks.
At the same time, they use modern "Sandboxing" techniques to protect your system and ensure that you are always aware of what actions the apps are permitted to take, such as reading and writing files, communicating over the internet, or accessing your camera, microphone, and other connected devices.
And since they rely on the native frameworks of the system, they tend to be quite compact (a few megabytes compressed), and so are quicker to download and launch than a typical web app.
### Getting Started
The App Fair catalog browser app can be installed on macOS 12.5 "Monterey" by downloading [App-Fair-macOS.zip](https://github.com/App-Fair/App/releases/latest/download/App-Fair-macOS.zip).
The app can be dragged from the Downloads folder into the `/Applications` folder, from where it can be launched.
Alternatively, [homebrew](https://brew.sh) users can install the App Fair app with the command:
```
brew install appfair/app/app-fair
```
And for those who want a headless installation but do not have homebrew,
the app can be downloaded and installed fresh with the command:
```
bash -c "$(curl -fsSL https://appfair.net/install.sh)"
```
Both of these commands will download the latest release zip and install it directly into your `/Applications/` folder.
From there, you can launch the <a href="https://appfair.app" target="_blank">`App Fair.app`</a> catalog browser application to start searching for apps to install.
### App Fair Usage
<img align="right" width="50%" alt="App Fair Browser App Preferences" src="assets/app-fair-prefs.png" />