Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ Hinweise für Beiträge und den DCO-Sign-off stehen in
[CONTRIBUTING.md](CONTRIBUTING.md). Der
[Verhaltenskodex](CODE_OF_CONDUCT.md) regelt die Zusammenarbeit, die
[Security Policy](SECURITY.md) die vertrauliche Meldung von Schwachstellen.
Der [öffentliche Release-Prozess](RELEASING.md) beschreibt Versionierung,
Prüfungen und reproduzierbare Release-Artefakte.
[Datenschutz](PRIVACY.md), [Nutzungsbedingungen](TERMS.md) und der
[Hinweis](NOTICE) dokumentieren Datenfluss und Lizenzgrenzen.

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ SourceBraid is fully open source under the [MIT License](LICENSE). See
[CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidance and DCO sign-off,
the [Code of Conduct](CODE_OF_CONDUCT.md) for community standards, and the
[Security Policy](SECURITY.md) for private vulnerability reporting. The
[public release process](RELEASING.md) documents versioning, validation, and
reproducible release artifacts. The
[privacy notice](PRIVACY.md), [terms](TERMS.md), and [notice](NOTICE) document
the local, user-controlled data flow and licensing boundaries.

Expand Down
136 changes: 136 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Releasing SourceBraid

This document describes the reproducible, public part of a SourceBraid release.
Store credentials, account verification, legal attestations, review accounts,
and final submission decisions are intentionally maintained outside the public
repository.

No Chrome Web Store, ChatGPT/Codex directory, or App Store release has been
published yet. The first coordinated public release should use `1.0.0` as its
customer-facing version unless the maintainers document a different decision.

## Release principles

- Build and tag releases from a clean commit on the public `main` branch.
- Never merge private repository history into this repository.
- Never include `website/`, `web-clips/`, credentials, local configuration,
Keychain data, caches, indexes, or generated build directories in a release.
- Use the checked-in package builders. They construct archives from explicit
allowlists instead of copying the repository broadly.
- Preserve source provenance and use only synthetic or redistributable content
in release screenshots and examples.
- Every pull-request commit must carry a DCO `Signed-off-by:` trailer.

## Version alignment

Before creating the first release candidate, align these customer-facing
versions:

- Chrome: `version` in `manifest.json`.
- ChatGPT/Codex skills package: `version` in
`codex-plugin/sourcebraid/.codex-plugin/plugin.json`.
- iOS app and Share Extension: `MARKETING_VERSION` in
`ios/SourceBraid.xcodeproj/project.pbxproj`.

Chrome versions use one to four dot-separated integers. The plugin uses semantic
versioning. After the first iOS upload, increase `CURRENT_PROJECT_VERSION` for
every new binary while keeping the app and Share Extension build numbers equal.

The first iOS publication uses the SourceBraid identities:

- app: `de.patrickschiller.sourcebraid`;
- Share Extension: `de.patrickschiller.sourcebraid.share`;
- App Group: `group.de.patrickschiller.sourcebraid`;
- shared Keychain group:
`$(AppIdentifierPrefix)de.patrickschiller.sourcebraid.shared`.

## Preflight checks

Run from the repository root:

```bash
git status --short --branch
node --test tests/capture-utils.test.js
python3 -m unittest discover -s tests -p "test_*.py"
```

Run the unsigned iOS build from `ios/`:

```bash
xcodebuild \
-project SourceBraid.xcodeproj \
-scheme SourceBraid \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
CODE_SIGNING_ALLOWED=NO \
build
```

Do not release while a required check fails or the worktree contains unrelated
changes.

## Chrome package

Build the Manifest V3 archive from its explicit allowlist:

```bash
python3 scripts/build_chrome_package.py
unzip -l dist/sourcebraid-chrome-v*.zip
```

The script prints the package path, version, SHA-256 digest, and file count. The
ZIP must contain `manifest.json` at its root and must not contain source archives,
the private website, plugin configuration, iOS sources, tests, Git metadata, or
local settings.

## ChatGPT and Codex skills package

Build the initial skills-only archive:

```bash
python3 scripts/build_plugin_package.py
unzip -l dist/sourcebraid-plugin-skills-v*.zip
```

The public package contains the three SourceBraid skills, their OpenAI metadata,
the dependency-free CLI, and listing assets. The builder intentionally removes
the local MCP server declaration and app entries from the packaged manifest.
Local repository installations can continue to use the complete plugin source.

## iOS archive

Confirm that the SourceBraid bundle identifiers, App Group, and Keychain access
group are registered for the selected Apple Developer team before enabling
signing. First validate the unsigned simulator build above. Then use the archive
and export commands in [`ios/README.md`](ios/README.md).

Signing and App Store upload credentials are not part of this repository. Never
commit provisioning profiles, certificates, export credentials, review tokens,
or App Store Connect API keys.

## GitHub setup script

Validate the user-facing repository bootstrap workflow without changing a
repository:

```bash
python3 scripts/setup_github.py --repo OWNER/REPOSITORY --dry-run
```

The setup script must continue to refuse public archive repositories, preserve
existing files, avoid printing credentials, and upload only its documented
allowlist.

## Tag and publish artifacts

1. Review the complete diff from the previous release tag, or the repository
root commit for the first release.
2. Record the passing check results and package SHA-256 digests.
3. Create an annotated version tag on the reviewed public commit.
4. Push the tag to the public repository.
5. Attach the Chrome and skills ZIP files and their digests to the corresponding
GitHub release when binary artifacts are distributed there.
6. Verify that every published archive can be traced back to the tagged commit.

Store review and publication remain separate maintainer actions. A GitHub tag or
release must not imply that a store submission has already been approved.
10 changes: 5 additions & 5 deletions ios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ The iOS project contains a SwiftUI configuration app and a native Share Extensio
2. Select the **SourceBraid** project and the **SourceBraid** target.
3. Under **Signing & Capabilities**, select your Apple Developer team.
4. Repeat for the **SourceBraidShare** target.
5. The existing TestFlight app keeps its pre-rebrand bundle identifiers `de.patrickschiller.stowmark` and `de.patrickschiller.stowmark.share`; changing them would create a different app instead of an update.
6. Keep the pre-rebrand App Group identical in both targets: `group.de.patrickschiller.stowmark`. This preserves settings and Keychain access across the SourceBraid rename.
5. Register or select the SourceBraid bundle identifiers `de.patrickschiller.sourcebraid` and `de.patrickschiller.sourcebraid.share`.
6. Register the App Group `group.de.patrickschiller.sourcebraid`, enable it for both targets, and keep the shared Keychain access group aligned with the entitlements.
7. Run the SourceBraid app on your iPhone once and configure GitHub.

The fine-grained GitHub token needs `Contents: Read and write` for the private SourceBraid repository. It is stored in a Keychain access group shared only by the app and extension.
Expand Down Expand Up @@ -38,9 +38,9 @@ xcodebuild \
-allowProvisioningUpdates
```

The export options upload the archive directly to App Store Connect. The existing
app record uses bundle ID `de.patrickschiller.stowmark`; its customer-facing name
is **SourceBraid**.
The export options upload the archive directly to App Store Connect. Create the
initial app record with bundle ID `de.patrickschiller.sourcebraid` and the
customer-facing name **SourceBraid** before the first upload.

## Use

Expand Down
12 changes: 6 additions & 6 deletions ios/SourceBraid.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.2.0;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.stowmark;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.sourcebraid;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
Expand Down Expand Up @@ -490,7 +490,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.2.0;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.stowmark;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.sourcebraid;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
Expand All @@ -516,7 +516,7 @@
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 0.2.0;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.stowmark.share;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.sourcebraid.share;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
Expand All @@ -543,7 +543,7 @@
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 0.2.0;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.stowmark.share;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.sourcebraid.share;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
Expand All @@ -566,7 +566,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.stowmark.tests;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.sourcebraid.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = iphonesimulator;
SWIFT_VERSION = 5.0;
Expand All @@ -586,7 +586,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.stowmark.tests;
PRODUCT_BUNDLE_IDENTIFIER = de.patrickschiller.sourcebraid.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = iphonesimulator;
SWIFT_VERSION = 5.0;
Expand Down
2 changes: 1 addition & 1 deletion ios/SourceBraid/Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>SourceBraidKeychainAccessGroup</key>
<string>$(AppIdentifierPrefix)de.patrickschiller.stowmark.shared</string>
<string>$(AppIdentifierPrefix)de.patrickschiller.sourcebraid.shared</string>
<key>UILaunchScreen</key>
<dict/>
<key>UISupportedInterfaceOrientations</key>
Expand Down
4 changes: 2 additions & 2 deletions ios/SourceBraid/Resources/SourceBraid.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.de.patrickschiller.stowmark</string>
<string>group.de.patrickschiller.sourcebraid</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)de.patrickschiller.stowmark.shared</string>
<string>$(AppIdentifierPrefix)de.patrickschiller.sourcebraid.shared</string>
</array>
</dict>
</plist>
4 changes: 2 additions & 2 deletions ios/SourceBraid/Shared/SourceBraidEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import Foundation

enum SourceBraidEnvironment {
// Keep the pre-rebrand identifiers so TestFlight upgrades retain settings and credentials.
static let appGroupIdentifier = "group.de.patrickschiller.stowmark"
static let keychainService = "de.patrickschiller.stowmark"
static let appGroupIdentifier = "group.de.patrickschiller.sourcebraid"
static let keychainService = "de.patrickschiller.sourcebraid"
static let keychainAccount = "github-token"
static let recentCapturesKey = "recent-captures"

Expand Down
2 changes: 1 addition & 1 deletion ios/SourceBraidShare/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>SourceBraidKeychainAccessGroup</key>
<string>$(AppIdentifierPrefix)de.patrickschiller.stowmark.shared</string>
<string>$(AppIdentifierPrefix)de.patrickschiller.sourcebraid.shared</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
Expand Down
4 changes: 2 additions & 2 deletions ios/SourceBraidShare/SourceBraidShare.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.de.patrickschiller.stowmark</string>
<string>group.de.patrickschiller.sourcebraid</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)de.patrickschiller.stowmark.shared</string>
<string>$(AppIdentifierPrefix)de.patrickschiller.sourcebraid.shared</string>
</array>
</dict>
</plist>