diff --git a/.github/actions/macos-build/action.yml b/.github/actions/macos-build/action.yml deleted file mode 100644 index 603cdc15..00000000 --- a/.github/actions/macos-build/action.yml +++ /dev/null @@ -1,68 +0,0 @@ -#Xamarin.Mac -> 6.12 -#iOS 16.2 -> 16.4 -#macOS (Cocoa) 9.1 -> 9.3 -#.NET -> 6.0 -#.NET -> 7.0 -#Visual Studio 17.5 -> 17.6 -name: Build for macOS -description: Core build steps for macOS -inputs: - configuration: - description: The configuration to build, like "Debug" - required: true - default: Debug - artifact_tag: - description: A string to tag the build artifact, like "Debug" or "MAS" - required: false - default: "" - sign: - description: Whether to sign the build artifact ("YES" or "NO") - required: false - default: "NO" - AC_USERNAME: - description: App Store Connect user name - required: false - default: "" - AC_PASSWORD: - description: App Store Connect password - required: false - default: "not set" -runs: - using: composite - steps: - # Note that runs.env doesn't work in composite actions - - name: "Build for Mac: ${{ inputs.configuration }}" - env: - AC_USERNAME: ${{ inputs.AC_USERNAME }} - AC_PASSWORD: ${{ inputs.AC_PASSWORD }} - CODE_SIGNING_ALLOWED: ${{ inputs.sign }} - CODE_SIGNING_REQUIRED: ${{ inputs.sign }} - ARTIFACT_TAG: ${{ inputs.configuration == 'Release_DevID' && 'notarizeMe' || inputs.artifact_tag }} - shell: bash - run: | - set -x # debug trace - msbuild -m -t:Restore -p:Configuration=${{ inputs.configuration }}_Mac scratch-link.sln - '/Applications/Visual Studio.app/Contents/MacOS/vstool' build -t:Build -c:'${{ inputs.configuration }}_Mac' "${PWD}/scratch-link.sln" - # "for" is just a convenient way to resolve the glob to a variable so we can DRY the filename for "if" and "mv" - for PKGPATH in scratch-link-mac/bin/"${{ inputs.configuration }}"/"Scratch Link"*.pkg; do - if [ -r "$PKGPATH" ]; then - # Get filename without path - PKGFILE="${PKGPATH##*/}" - if [ -n "${{ inputs.artifact_tag }}" ]; then - # change "Scratch Link-1.2.3" to "Scratch Link-Debug-1.2.3" - PKGFILE="${PKGFILE/Scratch Link/Scratch Link-${{ inputs.artifact_tag }}}" - fi - mkdir -p Artifacts - fi - # this is outside the "if" to force an error if the file doesn't exist - mv -v "$PKGPATH" "Artifacts/${PKGFILE}" - done - - name: "Notarize build artifact" - if: env.ARTIFACT_TAG == 'notarizeMe' - shell: bash - run: | - for PKGPATH in Artifacts/"Scratch Link-notarizeMe"*.pkg; do - PKGFILE="${PKGPATH##*/}" - scratch-link-mac/notarize.sh edu.mit.scratch.scratch-link "${PKGPATH}" "${PKGPATH}" /tmp || rm -f "${PKGPATH}" - mv -v "${PKGPATH}" "Artifacts/${PKGFILE/Scratch Link-notarizeMe/Scratch Link}" - done diff --git a/.github/actions/windows-build/action.yml b/.github/actions/windows-build/action.yml deleted file mode 100644 index a00fc4b9..00000000 --- a/.github/actions/windows-build/action.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Build for Windows -description: Core build steps for Windows -inputs: - configuration: - description: The configuration to build, like "Debug" - required: true - default: Debug - artifact_tag: - description: A string to tag the build artifact, like "Debug" or "MAS" - required: false - default: "" -runs: - using: composite - steps: - - name: "Build for Windows: ${{ inputs.configuration }}" - shell: pwsh - run: | - # Build the MSIX project instead of the Solution because msbuild gets grumpy about the Mac project. - # That means SolutionDir needs to be set artificially, though. - # The `UapAppxPackageBuildMode=StoreAndSideload` means it'll build both MSIXUpload and MSIXBundle. - # The StoreUpload mode does that too, but that might be a bug, and semantically "StoreAndSideload" is what we want. - msbuild scratch-link-win-msix/scratch-link-win-msix.wapproj -maxCpuCount -restore -t:Build -p:SolutionDir="$PWD\" -p:Configuration="${{ inputs.configuration }}_Win" -p:AppxBundlePlatforms="x86|x64|ARM64" -p:AppxBundle=Always -p:UapAppxPackageBuildMode=StoreAndSideload - - name: "Move Windows artifacts into place: ${{ inputs.configuration }}" - shell: bash - run: | - mkdir -p Artifacts - # The store package is fine as is: no user will see this filename. - mv -v scratch-link-win-msix/AppPackages/scratch-link-win-msix_*_${{ inputs.configuration }}_Win.msixupload Artifacts/ - # Transform the bundle for a more user-friendly filename - for PKGPATH in scratch-link-win-msix/AppPackages/scratch-link-win-msix_*_${{ inputs.configuration }}_Win_Test/scratch-link-win-msix_*_${{ inputs.configuration }}_Win.msixbundle; do - if [ -r "$PKGPATH" ]; then - PKGFILE="${PKGPATH##*/}" - [[ $PKGFILE =~ scratch-link-win-msix_([.0-9]+)_(.*)_${{ inputs.configuration }}_Win.msixbundle$ ]] - PKGVERSION=${BASH_REMATCH[1]} - PKGPLATFORMS=${BASH_REMATCH[2]} - fi - # do the move outside the "if" above to force an error if the file doesn't exist - if [ -z "${{ inputs.artifact_tag }}" ]; then - mv -v "$PKGPATH" "Artifacts/Scratch Link ${PKGVERSION}.msixbundle" - else - mv -v "$PKGPATH" "Artifacts/Scratch Link ${PKGVERSION} ${{ inputs.artifact_tag }}.msixbundle" - fi - done diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 31164b11..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,201 +0,0 @@ -name: CI build - -on: - push: # Runs whenever a commit is pushed to the repository, including for a PR - workflow_call: # Runs when this workflow is called from another workflow - workflow_dispatch: # Allows you to run this workflow manually from the Actions tab - -concurrency: - group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' - cancel-in-progress: true - -permissions: - contents: write # publish a GitHub release - issues: write # comment on released issues - pull-requests: write # comment on released pull requests - -jobs: - # Keep in mind: - # 60 seconds on Ubuntu = 1 minute charged to account - # 60 seconds on Windows = 2 minutes charged to account - # 60 seconds on macOS = 10 minutes charged to account - semver: - runs-on: ubuntu-latest - outputs: - version: ${{ steps.semver.outputs.SCRATCH_VERSION }} - hash: ${{ steps.semver.outputs.SCRATCH_HASH }} - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 - - uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3 - with: - cache: 'npm' - node-version-file: '.nvmrc' - - run: npm ci - - name: Make local 'remote' for semantic-release - run: | - # semantic-release tracks channels with notes, so we need to grab those from the real remote - # semantic-release also wants to inspect every branch listed in its "branches" setting - git fetch -uf origin main:main develop:develop 'refs/notes/*:refs/notes/*' - git clone . --bare --mirror semantic-release-remote # mirror copies notes - git remote set-url origin "file://$(realpath semantic-release-remote)" # semantic-release needs a proper URL - - name: Stage semantic-release version commit - # In release branches, this will calculate the version and save that to package.json so the build can use it. - # In other branches, it'll just check the semantic-release config. - # Note that if semantic-release makes changes it will automatically push them. - # That's the whole reason for the weird "local remote" stuff. - # See also: https://github.com/semantic-release/semantic-release/issues/964 - run: npx --no -- semantic-release - - name: Output semantic-release version - id: semver - run: | - cat < "$GITHUB_OUTPUT" - SCRATCH_VERSION=$(node -p "require('./package.json').version") - SCRATCH_HASH=$(git rev-parse --short HEAD) - EOF - - name: Create artifact for semantic-release 'remote' - run: tar czvf semantic-release-remote.tgz semantic-release-remote - - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 - with: - name: semantic-release-remote - path: semantic-release-remote.tgz - retention-days: 1 # relevant if a failure prevents the delete step below - build: - needs: semver - defaults: - run: - shell: bash # even on Windows, unless otherwise specified - env: - SCRATCH_SHOULD_SIGN: "NO" # TODO - MATCH_STORAGE_MODE: git - MATCH_GIT_URL: ${{ secrets.FL_GIT_URL }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - FASTLANE_ACCESS_KEY: ${{ secrets.FASTLANE_ACCESS_KEY }} - strategy: - fail-fast: false - matrix: - image: [windows-latest, macos-latest] - runs-on: ${{ matrix.image }} - steps: - ### Shared prologue - - #- name: Setup upterm session - # uses: lhotari/action-upterm@v1 - # with: - # limit-access-to-users: cwillisf - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4 - with: - name: semantic-release-remote - path: . - - name: Restore semantic-release 'remote' - run: | - # this `tar` command replaces the usual "checkout" step - tar xzvf semantic-release-remote.tgz - rm semantic-release-remote.tgz - - name: Pull semantic-release changes from local 'remote' - run: | - git remote add semantic-release semantic-release-remote - git pull --tags semantic-release ${{ github.ref_name }} - git fetch semantic-release 'refs/notes/*:refs/notes/*' # semantic-release tracks channels with notes - - ### macOS setup - - - name: "macOS: Setup keys for Fastlane" - if: runner.os == 'macOS' && env.FASTLANE_ACCESS_KEY != '' - uses: webfactory/ssh-agent@d4b9b8ff72958532804b70bbe600ad43b36d5f2e # v0.8.0 - with: - ssh-private-key: ${{ secrets.FASTLANE_ACCESS_KEY }} - - name: "macOS: Fastlane Match" - if: runner.os == 'macOS' && env.MATCH_PASSWORD != '' - shell: bash - run: fastlane circleci - - name: "macOS: Setup Xamarin" - if: runner.os == 'macOS' - shell: bash - run: | - #cat "$VM_ASSETS/select-xamarin-sdk-v2.sh" - #ls /Library/Frameworks/{Mono,Xamarin.Mac,Xamarin.iOS,Xamarin.Android}.framework/Versions/ - # For Xcode 13.2 / macOS 11: --mono=6.12 --mac=8.8 --ios=15.8 - # For Xcode 14.2 / macOS 12: --mono=6.12 --mac=9.1 --ios=16.2 - $VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --mac=9.1 --ios=16.2 - - ### Windows setup - - - name: "Windows: Add msbuild to PATH" - if: runner.os == 'Windows' - uses: microsoft/setup-msbuild@34cfbaee7f672c76950673338facd8a73f637506 # v1.1 - - ### Shared setup - - - name: Setup dotnet - uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3 - with: - dotnet-version: '6.0.x' - - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3 - with: - path: ~/.nuget/packages - # Look to see if there is a cache hit for the corresponding requirements file - key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} - restore-keys: ${{ runner.os }}-nuget - - ### macOS build - - - name: Build for macOS debug - if: runner.os == 'macOS' && env.SCRATCH_SHOULD_SIGN != 'YES' - uses: ./.github/actions/macos-build - with: - configuration: Debug - artifact_tag: Debug - sign: ${{ env.SCRATCH_SHOULD_SIGN }} - AC_USERNAME: ${{ secrets.AC_USERNAME }} - AC_PASSWORD: ${{ secrets.AC_PASSWORD }} - - name: Build for macOS direct download - if: runner.os == 'macOS' && env.SCRATCH_SHOULD_SIGN == 'YES' - uses: ./.github/actions/macos-build - with: - configuration: Release_DevID - artifact_tag: '' - sign: ${{ env.SCRATCH_SHOULD_SIGN }} - AC_USERNAME: ${{ secrets.AC_USERNAME }} - AC_PASSWORD: ${{ secrets.AC_PASSWORD }} - - name: Build for Mac App Store - if: runner.os == 'macOS' && env.SCRATCH_SHOULD_SIGN == 'YES' - uses: ./.github/actions/macos-build - with: - configuration: Release_MAS - artifact_tag: MAS - sign: ${{ env.SCRATCH_SHOULD_SIGN }} - AC_USERNAME: ${{ secrets.AC_USERNAME }} - AC_PASSWORD: ${{ secrets.AC_PASSWORD }} - - ### Windows build - - - name: Build for Windows debug - if: runner.os == 'Windows' && env.SCRATCH_SHOULD_SIGN != 'YES' - uses: ./.github/actions/windows-build - with: - configuration: Debug - artifact_tag: Debug - - name: Build for Windows release - if: runner.os == 'Windows' && env.SCRATCH_SHOULD_SIGN == 'YES' - uses: ./.github/actions/windows-build - with: - configuration: Release - artifact_tag: '' - - ### Shared epilogue - - - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 - with: - name: "Scratch ${{ needs.semver.outputs.version }} (${{ needs.semver.outputs.hash }})" - path: Artifacts/ - - finish: - if: always() # even if the build fails - runs-on: ubuntu-latest - needs: build - steps: - - uses: geekyeggo/delete-artifact@54ab544f12cdb7b71613a16a2b5a37a9ade990af # v2 - with: - name: semantic-release-remote - failOnError: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..eee5b6e6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,212 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + - 'v*.*.*-*' + workflow_dispatch: + inputs: + channel: + description: 'Override channel (auto/stable/dev). auto=태그 형식으로 결정' + type: choice + options: [auto, stable, dev] + default: auto + ref: + description: '수동 실행 시 사용할 ref (태그/브랜치). 비우면 워크플로 ref 사용' + type: string + default: '' + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + +jobs: + release: + runs-on: windows-latest + defaults: + run: + shell: bash + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.event.inputs.ref || github.ref }} + + - name: Resolve channel and version + id: meta + run: | + set -euo pipefail + # 채널 결정 + input="${{ github.event.inputs.channel }}" + tag_name="${GITHUB_REF_NAME:-}" + if [[ "$input" == "stable" || "$input" == "dev" ]]; then + channel="$input" + elif [[ "$tag_name" =~ ^v[0-9]+\.[0-9]+\.[0-9]+- ]]; then + channel="dev" + elif [[ "$tag_name" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + channel="stable" + else + channel="dev" # workflow_dispatch + auto + non-tag ref → 안전한 쪽 + fi + # 버전 산출 (태그면 v 제거, 아니면 git describe) + if [[ "$tag_name" =~ ^v ]]; then + version="${tag_name#v}" + else + version="$(git describe --tags --always --dirty)" + fi + # 채널별 버킷·distribution + if [[ "$channel" == "stable" ]]; then + bucket="scratch-link.aluxcoding.com" + dist_id="${{ secrets.CF_DIST_ID_PROD }}" + else + bucket="dev-scratch-link.aluxcoding.com" + dist_id="${{ secrets.CF_DIST_ID_DEV }}" + fi + { + echo "channel=$channel" + echo "version=$version" + echo "bucket=$bucket" + echo "dist_id=$dist_id" + } | tee -a "$GITHUB_OUTPUT" + + - name: Show resolved metadata + run: | + echo "channel = ${{ steps.meta.outputs.channel }}" + echo "version = ${{ steps.meta.outputs.version }}" + echo "bucket = ${{ steps.meta.outputs.bucket }}" + echo "dist_id = (마스킹됨)" + + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Verify build toolchain + shell: pwsh + run: | + dotnet --version + msbuild -version + aws --version + + - name: Restore NuGet cache + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json', '**/*.csproj', '**/*.props') }} + restore-keys: ${{ runner.os }}-nuget- + + - name: Build MSIX bundle + shell: pwsh + env: + SOLUTION_DIR: ${{ github.workspace }} + run: | + msbuild aluxlabs-link-win-msix/aluxlabs-link-win-msix.wapproj ` + -maxCpuCount ` + -restore ` + -t:Build ` + -p:SolutionDir="$env:SOLUTION_DIR\" ` + -p:Configuration=Release_Win ` + -p:AppxBundlePlatforms="x86|x64|ARM64" ` + -p:AppxBundle=Always ` + -p:UapAppxPackageBuildMode=StoreAndSideload + + - name: Collect artifacts + shell: bash + run: | + set -euo pipefail + mkdir -p Artifacts + + version="${{ steps.meta.outputs.version }}" + channel="${{ steps.meta.outputs.channel }}" + bundle_src=$(find aluxlabs-link-win-msix/AppPackages -type f -name '*.msixbundle' | head -n1) + upload_src=$(find aluxlabs-link-win-msix/AppPackages -type f -name '*.msixupload' | head -n1) + + if [[ -z "$bundle_src" || -z "$upload_src" ]]; then + echo "::error::빌드 산출물(.msixbundle / .msixupload)을 찾지 못함" + ls -R aluxlabs-link-win-msix/AppPackages || true + exit 1 + fi + + bundle_dst="Artifacts/AluxLabs-Link-${version}.msixbundle" + upload_dst="Artifacts/AluxLabs-Link-${version}.msixupload" + cp "$bundle_src" "$bundle_dst" + cp "$upload_src" "$upload_dst" + + # 체크섬 + (cd Artifacts && sha256sum "$(basename "$bundle_dst")" "$(basename "$upload_dst")") > Artifacts/SHA256SUMS.txt + + # latest.json + sha=$(sha256sum "$bundle_dst" | awk '{print $1}') + size=$(stat -c %s "$bundle_dst" 2>/dev/null || stat -f %z "$bundle_dst") + published=$(date -u +%Y-%m-%dT%H:%M:%SZ) + archive_url="https://${{ steps.meta.outputs.bucket }}/archive/v${version}/$(basename "$bundle_dst")" + + jq -n \ + --arg version "$version" \ + --arg publishedAt "$published" \ + --arg channel "$channel" \ + --arg url "$archive_url" \ + --arg sha256 "$sha" \ + --argjson size "$size" \ + '{version:$version, publishedAt:$publishedAt, channel:$channel, url:$url, sha256:$sha256, size:$size, minWindowsBuild:17763, windowsAppRuntime:"1.8"}' \ + > Artifacts/latest.json + + ls -la Artifacts/ + cat Artifacts/latest.json + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Upload archive (immutable) + shell: bash + run: | + set -euo pipefail + version="${{ steps.meta.outputs.version }}" + bucket="${{ steps.meta.outputs.bucket }}" + aws s3 cp Artifacts/ "s3://${bucket}/archive/v${version}/" \ + --recursive \ + --exclude "latest.json" \ + --cache-control "public, max-age=31536000, immutable" \ + --metadata-directive REPLACE + + - name: Upload latest pointers (short cache) + shell: bash + run: | + set -euo pipefail + version="${{ steps.meta.outputs.version }}" + bucket="${{ steps.meta.outputs.bucket }}" + aws s3 cp "Artifacts/AluxLabs-Link-${version}.msixbundle" \ + "s3://${bucket}/latest.msixbundle" \ + --cache-control "public, max-age=300" \ + --content-type "application/vnd.ms-appx" + aws s3 cp Artifacts/latest.json \ + "s3://${bucket}/latest.json" \ + --cache-control "public, max-age=300" \ + --content-type "application/json" + + - name: Invalidate CloudFront latest paths + shell: bash + run: | + set -euo pipefail + # native aws.exe + Git Bash 조합 회피: --invalidation-batch에 workspace 상대 JSON 파일 전달. + # CallerReference로 재실행 중복 방지. + printf '{"Paths":{"Quantity":2,"Items":["/latest.msixbundle","/latest.json"]},"CallerReference":"release-%s-%s"}' \ + "${{ github.run_id }}" "${{ github.run_attempt }}" > cf-inv.json + cat cf-inv.json + aws cloudfront create-invalidation \ + --distribution-id "${{ steps.meta.outputs.dist_id }}" \ + --invalidation-batch file://cf-inv.json \ + --query 'Invalidation.{Id:Id,Status:Status}' \ + --output table diff --git a/.github/workflows/signature-assistant.yml b/.github/workflows/signature-assistant.yml index acd2c3bb..be51a8c1 100644 --- a/.github/workflows/signature-assistant.yml +++ b/.github/workflows/signature-assistant.yml @@ -1,9 +1,13 @@ name: "Signature Assistant" on: - issue_comment: - types: [created] - pull_request_target: - types: [opened,closed,synchronize] + # Scratch Foundation의 CLA 서명 검사 봇. AluxLabs Link fork는 upstream에 기여하는 + # 워크플로가 아니므로 자동 트리거를 비활성화한다. (scratchfoundation/scratch-agreements + # 접근 PAT가 우리 저장소에 없어 매번 실패만 함.) + # issue_comment: + # types: [created] + # pull_request_target: + # types: [opened,closed,synchronize] + workflow_dispatch: # 수동 실행만 허용 permissions: actions: write diff --git a/.gitignore b/.gitignore index 915bf3e7..f1773c63 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,17 @@ Package.StoreAssociation.xml **/fastlane/report.xml **/fastlane/screenshots **/fastlane/test_output + +# Visual Studio project upgrade artifacts +UpgradeLog*.htm +_UpgradeReport_Files/ +Backup*/ + +# Local-only debug captures (DebugView dumps, browser console logs, etc.) +ref/ + +# Test signing materials (self-signed test certs / build logs — never commit) +/aluxlabs-link-win-msix/_signing/ + +# Staged distribution bundles (서명된 .msixbundle — 대용량이라 커밋 금지. .appinstaller 템플릿은 dist/ 직하에 별도 커밋) +/aluxlabs-link-win-msix/dist/upload/ diff --git a/Scratch Link Safari Helper/.gitignore b/AluxLabs Link Safari Helper/.gitignore similarity index 100% rename from Scratch Link Safari Helper/.gitignore rename to AluxLabs Link Safari Helper/.gitignore diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Scratch_Link_Safari_Extension.entitlements b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/AluxLabs_Link_Safari_Extension.entitlements similarity index 86% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Scratch_Link_Safari_Extension.entitlements rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/AluxLabs_Link_Safari_Extension.entitlements index 4d459d9f..fd948774 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/Scratch_Link_Safari_Extension.entitlements +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/AluxLabs_Link_Safari_Extension.entitlements @@ -9,7 +9,7 @@ com.apple.security.network.client com.apple.application-identifier - W7AR3WMP87.edu.mit.scratch.scratch-link.safari-extension + W7AR3WMP87.com.aluxlabs.link.safari-extension com.apple.developer.team-identifier W7AR3WMP87 diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Info.plist b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Info.plist similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Info.plist rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Info.plist diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/JSON.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/JSON.swift similarity index 91% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/JSON.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/JSON.swift index 7485437c..55bdaa3f 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/JSON.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/JSON.swift @@ -1,6 +1,6 @@ // // JSONPromise.swift -// Scratch Link Safari Extension +// AluxLabs Link Safari Extension // // Created by Christopher Willis-Ford on 3/30/22. // diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Makefile b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Makefile similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Makefile rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Makefile diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/_locales/en/messages.json b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/_locales/en/messages.json similarity index 81% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/_locales/en/messages.json rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/_locales/en/messages.json index 749a0aba..09caa613 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/_locales/en/messages.json +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/_locales/en/messages.json @@ -1,10 +1,10 @@ { "extension_name": { - "message": "Scratch Link", + "message": "AluxLabs Link", "description": "The display name for the extension." }, "extension_description": { - "message": "This extension allows Safari to communicate with Scratch Link.", + "message": "This extension allows Safari to communicate with AluxLabs Link.", "description": "Description of what the extension does." } } diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/scratch-link-extension-background.js b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/aluxlabs-link-extension-background.js similarity index 90% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/scratch-link-extension-background.js rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/aluxlabs-link-extension-background.js index c38e4cad..5443a729 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/scratch-link-extension-background.js +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/aluxlabs-link-extension-background.js @@ -43,18 +43,18 @@ browser.runtime.onMessage.addListener((request, sender, sendResponse) => { // handle a connection coming from a content script browser.runtime.onConnect.addListener(port => { // handle a message from the content script session associated with this port - port.onMessage.addListener(messageToScratchLink => { - const {session, method, params, id} = messageToScratchLink; + port.onMessage.addListener(messageToAluxLabsLink => { + const {session, method, params, id} = messageToAluxLabsLink; - // forward the message to the native app (which will forward it to Scratch Link) + // forward the message to the native app (which will forward it to AluxLabs Link) browser.runtime.sendNativeMessage(appId, { session, method, params, id - }, responseFromScratchLink => { + }, responseFromAluxLabsLink => { // send the native app's response back to the content script session - port.postMessage(responseFromScratchLink); + port.postMessage(responseFromAluxLabsLink); } ); } ); }); diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/scratch-link-extension.js b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/aluxlabs-link-extension.js similarity index 67% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/scratch-link-extension.js rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/aluxlabs-link-extension.js index ef98f595..6c5ee567 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/scratch-link-extension.js +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/aluxlabs-link-extension.js @@ -1,7 +1,7 @@ (function() { // If the native app sends a message to the background script, the Safari window pops to the front and steals focus. // Also, Safari unloads the native app if comms are idle for ~5 seconds. - // We can solve both of these problems by polling for messages from Scratch Link. + // We can solve both of these problems by polling for messages from AluxLabs Link. // Scratch projects generally run at 30 Hz max, so keep pollFrequency >= 30. // The browser will enforce some minimum amount of time (4 ms or more by spec), so at some point making this "faster" won't work. // TODO: consider polling for all sessions in this context at once instead of each independently. @@ -10,19 +10,19 @@ const pageSessions = new Map(); /** - * Check for an element in the document with id='scratch-link-extension-script'. + * Check for an element in the document with id='aluxlabs-link-extension-script'. * If found, inject the socket script into it. */ - const injectScratchLinkScript = () => { - const extensionScriptNode = document.getElementById("scratch-link-extension-script"); + const injectAluxLabsLinkScript = () => { + const extensionScriptNode = document.getElementById("aluxlabs-link-extension-script"); if (extensionScriptNode) { extensionScriptNode.innerHTML = ""; // make it safe to change "type" extensionScriptNode.type = "module"; extensionScriptNode.innerHTML = [ - `import("${browser.runtime.getURL("web/scratch-link-safari-socket.mjs")}").then(`, + `import("${browser.runtime.getURL("web/aluxlabs-link-safari-socket.mjs")}").then(`, " module => {", " self.Scratch = self.Scratch || {};", - " self.Scratch.ScratchLinkSafariSocket = module.ScratchLinkSafariSocket;", + " self.Scratch.AluxLabsLinkSafariSocket = module.AluxLabsLinkSafariSocket;", " }", ");" ].join("\n"); @@ -32,43 +32,43 @@ // This content script runs at "document_idle" (Document.readyState == complete) // so a static page should have this element ready by now. // If the script element is added dynamically, send the script injection message (see below). - injectScratchLinkScript(); + injectAluxLabsLinkScript(); // handle messages from the page self.addEventListener("message", event => { - const message = event.data["to-scratch-link"]; + const message = event.data["to-aluxlabs-link"]; if (message) { - onMessageToScratchLink(message, event.origin); - } else if (event.data["inject-scratch-link-script"]) { - injectScratchLinkScript(); + onMessageToAluxLabsLink(message, event.origin); + } else if (event.data["inject-aluxlabs-link-script"]) { + injectAluxLabsLinkScript(); } }); // handle messages from the background script browser.runtime.onMessage.addListener((outerMessage, sender, response) => { - const message = outerMessage["from-scratch-link"]; + const message = outerMessage["from-aluxlabs-link"]; if (message) { - // the client/page script needs the outerMessage so it can tell the message is from Scratch Link + // the client/page script needs the outerMessage so it can tell the message is from AluxLabs Link self.postMessage(outerMessage, self.origin); } }); /** - * Handles a message sent by the page and intended for Scratch Link. - * @param {object} messageToScratchLink - the "to-scratch-link" message from the page. + * Handles a message sent by the page and intended for AluxLabs Link. + * @param {object} messageToAluxLabsLink - the "to-aluxlabs-link" message from the page. * @param {string} origin - the origin of the page that sent the message. */ - const onMessageToScratchLink = async (messageToScratchLink, origin) => { - if (messageToScratchLink.method == "open") { - const openResponse = await browser.runtime.sendMessage(messageToScratchLink); + const onMessageToAluxLabsLink = async (messageToAluxLabsLink, origin) => { + if (messageToAluxLabsLink.method == "open") { + const openResponse = await browser.runtime.sendMessage(messageToAluxLabsLink); onSessionOpened(openResponse, origin); } else { - const sessionId = messageToScratchLink.session; + const sessionId = messageToAluxLabsLink.session; const port = pageSessions.get(sessionId); if (port) { - port.postMessage(messageToScratchLink); + port.postMessage(messageToAluxLabsLink); } else { - console.error("Scratch Link extension failed to find port for session", sessionId); + console.error("AluxLabs Link extension failed to find port for session", sessionId); } } }; @@ -77,7 +77,7 @@ // check for an error or otherwise bad response const sessionId = response.session; if (response.error || !sessionId || response.result !== sessionId) { - console.error("Scratch Link extension failed to open a session", response); + console.error("AluxLabs Link extension failed to open a session", response); return; } @@ -85,7 +85,7 @@ const port = browser.runtime.connect({name: sessionId.toString()}); pageSessions.set(sessionId, port); - // set up polling for messages from Scratch Link + // set up polling for messages from AluxLabs Link // we can reuse the same message repeatedly to save on GC const pollMessageId = 'web-extension-poll'; const sessionPollMessage = {method: 'poll', session: sessionId, id: pollMessageId}; @@ -107,27 +107,27 @@ // clean up on disconnect port.onDisconnect.addListener(() => { - console.log("Scratch Link extension disconnected a session", sessionId); + console.log("AluxLabs Link extension disconnected a session", sessionId); clearInterval(pollInterval); pageSessions.delete(response.session); }); - // forward messages from Scratch Link to the page - const onMessageFromScratchLink = messageFromScratchLink => { - switch (messageFromScratchLink.id) { + // forward messages from AluxLabs Link to the page + const onMessageFromAluxLabsLink = messageFromAluxLabsLink => { + switch (messageFromAluxLabsLink.id) { case pollMessageId: --pollPending; - handlePollResults(sessionId, messageFromScratchLink.result); + handlePollResults(sessionId, messageFromAluxLabsLink.result); break; default: - self.postMessage({"from-scratch-link": messageFromScratchLink}, origin); + self.postMessage({"from-aluxlabs-link": messageFromAluxLabsLink}, origin); break; } }; - port.onMessage.addListener(onMessageFromScratchLink); + port.onMessage.addListener(onMessageFromAluxLabsLink); // now that all the plumbing is ready, forward the 'open' message response to the page - onMessageFromScratchLink(response); + onMessageFromAluxLabsLink(response); }; const handlePollResults = (sessionId, messages) => { @@ -136,7 +136,7 @@ } for (let message of messages) { - self.postMessage({'from-scratch-link': { + self.postMessage({'from-aluxlabs-link': { session: sessionId, data: message }}, origin); diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-128.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-128.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-128.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-128.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-256.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-256.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-256.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-256.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-48.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-48.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-48.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-48.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-512.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-512.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-512.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-512.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-64.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-64.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-64.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-64.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-96.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-96.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/icon-96.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/icon-96.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-16.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-16.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-16.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-16.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-19.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-19.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-19.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-19.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-32.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-32.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-32.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-32.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-38.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-38.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-38.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-38.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-48.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-48.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-48.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-48.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-72.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-72.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/images/toolbar-icon-72.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/images/toolbar-icon-72.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/manifest.json b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/manifest.json similarity index 87% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/manifest.json rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/manifest.json index 4d1a476a..caee1069 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/manifest.json +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/manifest.json @@ -8,7 +8,7 @@ "version_name": "(placeholder for the user-friendly version number)", "web_accessible_resources": [ - "web/scratch-link-safari-socket.mjs" + "web/aluxlabs-link-safari-socket.mjs" ], "icons": { @@ -20,12 +20,12 @@ }, "background": { - "scripts": [ "scratch-link-extension-background.js" ], + "scripts": [ "aluxlabs-link-extension-background.js" ], "persistent": false }, "content_scripts": [{ - "js": [ "scratch-link-extension.js" ], + "js": [ "aluxlabs-link-extension.js" ], "matches": [ "" ] }], diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/web/scratch-link-safari-socket.mjs b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/web/aluxlabs-link-safari-socket.mjs similarity index 90% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/web/scratch-link-safari-socket.mjs rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/web/aluxlabs-link-safari-socket.mjs index db4871df..966c1271 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/Resources/web/scratch-link-safari-socket.mjs +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/Resources/web/aluxlabs-link-safari-socket.mjs @@ -50,7 +50,7 @@ const registerResponseHandlers = function (handlers) { * @param {MessageEvent} event - the message event to handle */ const messageListener = function (event) { - const message = event.data['from-scratch-link']; + const message = event.data['from-aluxlabs-link']; if (!message) return; if (message.id && openRequests.has(message.id)) { const handlers = openRequests.get(message.id); @@ -78,9 +78,9 @@ const installListener = () => { }; /** - * ScratchLinkSafariSocket class: represents a Scratch Link session socket using the Safari extension as transport. + * AluxLabsLinkSafariSocket class: represents a AluxLabs Link session socket using the Safari extension as transport. */ -class ScratchLinkSafariSocket { +class AluxLabsLinkSafariSocket { /** * Check if it appears that the extension is active and this socket class can be used. @@ -93,7 +93,7 @@ class ScratchLinkSafariSocket { } /** - * Construct a new Scratch Link session socket. + * Construct a new AluxLabs Link session socket. * @param {string} type - the type of session, like 'ble' */ constructor (type) { @@ -107,7 +107,7 @@ class ScratchLinkSafariSocket { } /** - * Open communication with Scratch Link. + * Open communication with AluxLabs Link. * Calls the `onOpen` callback when the connection is established. */ open () { @@ -171,7 +171,7 @@ class ScratchLinkSafariSocket { } /** - * Send a message to Scratch Link + * Send a message to AluxLabs Link * @param {object} messageObject - a JSON-RPC 2.0 message object */ sendMessage (messageObject) { @@ -208,7 +208,7 @@ class ScratchLinkSafariSocket { } /** - * @param {function} callback - the function to call when a message is received from Scratch Link + * @param {function} callback - the function to call when a message is received from AluxLabs Link */ setHandleMessage (callback) { this._handleMessage = callback; @@ -230,21 +230,21 @@ class ScratchLinkSafariSocket { } _sendNotify (method, params = {}) { - this._toScratchLink(method, params, false); + this._toAluxLabsLink(method, params, false); } _sendRequest (method, params = {}) { - return this._toScratchLink(method, params, true); + return this._toAluxLabsLink(method, params, true); } /** - * Send a notification or request to Scratch Link. + * Send a notification or request to AluxLabs Link. * @param {string} method - the method to call * @param {object} params - optional parameters for the call * @param {boolean} expectResponse - true to send a request, false for a notification * @returns {Promise|undefined} - a Promise for the result of the request, if expectResponse is true */ - _toScratchLink (method, params, expectResponse) { + _toAluxLabsLink (method, params, expectResponse) { const message = { jsonrpc: '2.0', session: this._id, @@ -257,9 +257,9 @@ class ScratchLinkSafariSocket { message.id = registerResponseHandlers({resolve, reject}); }); } - self.postMessage({'to-scratch-link': message}, self.origin); + self.postMessage({'to-aluxlabs-link': message}, self.origin); return responsePromise; } } -export { ScratchLinkSafariSocket }; +export { AluxLabsLinkSafariSocket }; diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/SafariWebExtensionHandler.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/SafariWebExtensionHandler.swift similarity index 94% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/SafariWebExtensionHandler.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/SafariWebExtensionHandler.swift index 9ac92647..4d23bd31 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/SafariWebExtensionHandler.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/SafariWebExtensionHandler.swift @@ -1,6 +1,6 @@ // // SafariWebExtensionHandler.swift -// Scratch Link Safari Extension +// AluxLabs Link Safari Extension // // Created by Christopher Willis-Ford on 3/16/22. // @@ -37,17 +37,17 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { func beginRequest(with context: NSExtensionContext) { guard let message = getMessage(from: context) else { - ScratchLog.log("could not retrieve message", type: .error) + AluxLabsLog.log("could not retrieve message", type: .error) return } guard let jsonMessage = message as? JSONObject else { - ScratchLog.log("ignoring malformed message", type: .error) + AluxLabsLog.log("ignoring malformed message", type: .error) return } guard let method = jsonMessage["method"] as? String else { - ScratchLog.log("ignoring message without method", type: .error) + AluxLabsLog.log("ignoring message without method", type: .error) return } @@ -147,7 +147,7 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { } func unrecognizedMethod(with sessionID: UInt32?, method: String, params: JSONObject?, id: JSONValue?, completion: @escaping (JSONValueResult) -> Void) -> Void { - ScratchLog.log("Ignoring call to unrecognized method: %{public}@", type: .error, method) + AluxLabsLog.log("Ignoring call to unrecognized method: %{public}@", type: .error, method) return completion(.failure("unrecognized method")) } diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/ScratchLog.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/ScratchLog.swift similarity index 53% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/ScratchLog.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/ScratchLog.swift index 65859774..3087e7ac 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/ScratchLog.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/ScratchLog.swift @@ -1,6 +1,6 @@ // -// ScratchLog.swift -// Scratch Link Safari Extension +// AluxLabsLog.swift +// AluxLabs Link Safari Extension // // Created by Christopher Willis-Ford on 9/30/22. // @@ -8,23 +8,23 @@ import Foundation import os.log -class ScratchLog { - public static let logSubsystem = "org.scratch.link"; +class AluxLabsLog { + public static let logSubsystem = "com.aluxlabs.link"; public static let logCategory = "safari-extension"; - public static let shared = ScratchLog() + public static let shared = AluxLabsLog() public static func log(_ message: StaticString, type: OSLogType = .default, _ args: CVarArg...) { shared.doLog(message, type: type, args) } - private let scratchLog: OSLog + private let aluxLabsLog: OSLog private init() { - self.scratchLog = OSLog(subsystem: ScratchLog.logSubsystem, category: ScratchLog.logCategory) + self.aluxLabsLog = OSLog(subsystem: AluxLabsLog.logSubsystem, category: AluxLabsLog.logCategory) } private func doLog(_ message: StaticString, type: OSLogType = .default, _ args: CVarArg...) { - os_log(message, log: scratchLog, type: type, args) + os_log(message, log: aluxLabsLog, type: type, args) } } diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/SessionDelegate.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/SessionDelegate.swift similarity index 88% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/SessionDelegate.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/SessionDelegate.swift index a639a233..7de7720f 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/SessionDelegate.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/SessionDelegate.swift @@ -1,6 +1,6 @@ // // SessionDelegate.swift -// Scratch Link Safari Extension +// AluxLabs Link Safari Extension // // Created by Christopher Willis-Ford on 3/30/22. // @@ -102,7 +102,7 @@ class SessionDelegate: NSObject, URLSessionWebSocketDelegate { if let openCallback = openCallback { openCallback(.failure("closed")) } - ScratchLog.log("session closed", type: .info) + AluxLabsLog.log("session closed", type: .info) let oldCallbacks = closeCallbacks closeCallbacks = [] for callback in oldCallbacks { @@ -111,42 +111,42 @@ class SessionDelegate: NSObject, URLSessionWebSocketDelegate { } private func listen() { - let messageMalformed: StaticString = "received malformed message from Scratch Link" + let messageMalformed: StaticString = "received malformed message from AluxLabs Link" func receiveHandler(result: Result) -> Void { switch result { case .success(let response): switch response { case .string(let responseText): if let responseJSON = try? JSONSerialization.jsonObject(with: responseText.data(using: .utf8)!, options: []) as? JSONObject { - onMessageFromScratchLink(responseJSON) + onMessageFromAluxLabsLink(responseJSON) } else { - ScratchLog.log(messageMalformed, type: .error) + AluxLabsLog.log(messageMalformed, type: .error) } case .data(let responseData): if let responseJSON = try? JSONSerialization.jsonObject(with: responseData, options: []) as? JSONObject { - onMessageFromScratchLink(responseJSON) + onMessageFromAluxLabsLink(responseJSON) } else { - ScratchLog.log(messageMalformed, type: .error) + AluxLabsLog.log(messageMalformed, type: .error) } break // TODO: use responseData @unknown default: break // TODO: report error } case .failure(let error): - ScratchLog.log("error receiving from Scratch Link: %{public}@", type: .error, String(describing: error)) + AluxLabsLog.log("error receiving from AluxLabs Link: %{public}@", type: .error, String(describing: error)) } if webSocket?.state == .running { webSocket?.receive(completionHandler: receiveHandler) } else { - ScratchLog.log("closing session: socket not running", type: .error) - onMessageFromScratchLink(["method": "sessionDidClose"]) + AluxLabsLog.log("closing session: socket not running", type: .error) + onMessageFromAluxLabsLink(["method": "sessionDidClose"]) } } webSocket?.receive(completionHandler: receiveHandler) } - private func onMessageFromScratchLink(_ receivedJSON: JSONObject) { + private func onMessageFromAluxLabsLink(_ receivedJSON: JSONObject) { if receivedJSON["method"] == nil, let id = receivedJSON["id"] as? JSONValue, let pendingRequest = pendingRequests[id] { diff --git a/Scratch Link Safari Helper/Scratch Link Safari Extension/inject-version-info.sh b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/inject-version-info.sh old mode 100755 new mode 100644 similarity index 97% rename from Scratch Link Safari Helper/Scratch Link Safari Extension/inject-version-info.sh rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/inject-version-info.sh index 69e3c596..1e8dcc33 --- a/Scratch Link Safari Helper/Scratch Link Safari Extension/inject-version-info.sh +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Extension/inject-version-info.sh @@ -1,7 +1,7 @@ #!/bin/bash # inject-version-info.sh -# Scratch Link Safari Helper +# AluxLabs Link Safari Helper # # Created by Christopher Willis-Ford on 9/7/22. # diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/project.pbxproj b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/project.pbxproj similarity index 75% rename from Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/project.pbxproj rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/project.pbxproj index 76f5159e..d320afbf 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/project.pbxproj +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/project.pbxproj @@ -18,16 +18,16 @@ 69E961C227E28B86008CF7C0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961C127E28B86008CF7C0 /* ViewController.swift */; }; 69E961C527E28B86008CF7C0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 69E961C327E28B86008CF7C0 /* Main.storyboard */; }; 69E961C727E28B88008CF7C0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69E961C627E28B88008CF7C0 /* Assets.xcassets */; }; - 69E961D327E28B88008CF7C0 /* Scratch_Link_Safari_HelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961D227E28B88008CF7C0 /* Scratch_Link_Safari_HelperTests.swift */; }; - 69E961DD27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961DC27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITests.swift */; }; - 69E961DF27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961DE27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITestsLaunchTests.swift */; }; - 69E961E527E28B88008CF7C0 /* Scratch Link Safari Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 69E961E427E28B88008CF7C0 /* Scratch Link Safari Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 69E961D327E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961D227E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperTests.swift */; }; + 69E961DD27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961DC27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITests.swift */; }; + 69E961DF27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961DE27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift */; }; + 69E961E527E28B88008CF7C0 /* AluxLabs Link Safari Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 69E961E427E28B88008CF7C0 /* AluxLabs Link Safari Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 69E961EA27E28B88008CF7C0 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E961E927E28B88008CF7C0 /* SafariWebExtensionHandler.swift */; }; 69E961ED27E28B88008CF7C0 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 69E961EC27E28B88008CF7C0 /* _locales */; }; 69E961EF27E28B88008CF7C0 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 69E961EE27E28B88008CF7C0 /* images */; }; - 69E961F327E28B88008CF7C0 /* scratch-link-extension.js in Resources */ = {isa = PBXBuildFile; fileRef = 69E961F227E28B88008CF7C0 /* scratch-link-extension.js */; }; - 69E961F527E28B88008CF7C0 /* scratch-link-extension-background.js in Resources */ = {isa = PBXBuildFile; fileRef = 69E961F427E28B88008CF7C0 /* scratch-link-extension-background.js */; }; - 69FCB6E028E750C400F753E6 /* ScratchLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69FCB6DF28E750C400F753E6 /* ScratchLog.swift */; }; + 69E961F327E28B88008CF7C0 /* aluxlabs-link-extension.js in Resources */ = {isa = PBXBuildFile; fileRef = 69E961F227E28B88008CF7C0 /* aluxlabs-link-extension.js */; }; + 69E961F527E28B88008CF7C0 /* aluxlabs-link-extension-background.js in Resources */ = {isa = PBXBuildFile; fileRef = 69E961F427E28B88008CF7C0 /* aluxlabs-link-extension-background.js */; }; + 69FCB6E028E750C400F753E6 /* AluxLabsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69FCB6DF28E750C400F753E6 /* AluxLabsLog.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -36,21 +36,21 @@ containerPortal = 69E961AA27E28B86008CF7C0 /* Project object */; proxyType = 1; remoteGlobalIDString = 69E961B127E28B86008CF7C0; - remoteInfo = "Scratch Link Safari Helper"; + remoteInfo = "AluxLabs Link Safari Helper"; }; 69E961D927E28B88008CF7C0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 69E961AA27E28B86008CF7C0 /* Project object */; proxyType = 1; remoteGlobalIDString = 69E961B127E28B86008CF7C0; - remoteInfo = "Scratch Link Safari Helper"; + remoteInfo = "AluxLabs Link Safari Helper"; }; 69E961E627E28B88008CF7C0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 69E961AA27E28B86008CF7C0 /* Project object */; proxyType = 1; remoteGlobalIDString = 69E961E327E28B88008CF7C0; - remoteInfo = "Scratch Link Safari Extension"; + remoteInfo = "AluxLabs Link Safari Extension"; }; /* End PBXContainerItemProxy section */ @@ -61,7 +61,7 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( - 69E961E527E28B88008CF7C0 /* Scratch Link Safari Extension.appex in Embed App Extensions */, + 69E961E527E28B88008CF7C0 /* AluxLabs Link Safari Extension.appex in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -82,7 +82,7 @@ 69C52B3027F50E57006A46F3 /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; 69E1236228A3536800F6AAD5 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 69E1236528A40EC000F6AAD5 /* web */ = {isa = PBXFileReference; lastKnownFileType = folder; path = web; sourceTree = ""; }; - 69E961B227E28B86008CF7C0 /* Scratch Link Safari Helper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Scratch Link Safari Helper.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 69E961B227E28B86008CF7C0 /* AluxLabs Link Safari Helper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AluxLabs Link Safari Helper.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 69E961B527E28B86008CF7C0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 69E961B927E28B86008CF7C0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Base; path = ../Base.lproj/Main.html; sourceTree = ""; }; 69E961BB27E28B86008CF7C0 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; @@ -91,23 +91,23 @@ 69E961C127E28B86008CF7C0 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 69E961C427E28B86008CF7C0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 69E961C627E28B88008CF7C0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 69E961C827E28B88008CF7C0 /* Scratch_Link_Safari_Helper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Scratch_Link_Safari_Helper.entitlements; sourceTree = ""; }; - 69E961C927E28B88008CF7C0 /* Scratch Link Safari Helper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Scratch Link Safari Helper.entitlements"; sourceTree = ""; }; - 69E961CE27E28B88008CF7C0 /* Scratch Link Safari HelperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Scratch Link Safari HelperTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 69E961D227E28B88008CF7C0 /* Scratch_Link_Safari_HelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scratch_Link_Safari_HelperTests.swift; sourceTree = ""; }; - 69E961D827E28B88008CF7C0 /* Scratch Link Safari HelperUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Scratch Link Safari HelperUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 69E961DC27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scratch_Link_Safari_HelperUITests.swift; sourceTree = ""; }; - 69E961DE27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scratch_Link_Safari_HelperUITestsLaunchTests.swift; sourceTree = ""; }; - 69E961E427E28B88008CF7C0 /* Scratch Link Safari Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Scratch Link Safari Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 69E961C827E28B88008CF7C0 /* AluxLabs_Link_Safari_Helper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AluxLabs_Link_Safari_Helper.entitlements; sourceTree = ""; }; + 69E961C927E28B88008CF7C0 /* AluxLabs Link Safari Helper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "AluxLabs Link Safari Helper.entitlements"; sourceTree = ""; }; + 69E961CE27E28B88008CF7C0 /* AluxLabs Link Safari HelperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "AluxLabs Link Safari HelperTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 69E961D227E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AluxLabs_Link_Safari_HelperTests.swift; sourceTree = ""; }; + 69E961D827E28B88008CF7C0 /* AluxLabs Link Safari HelperUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "AluxLabs Link Safari HelperUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 69E961DC27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AluxLabs_Link_Safari_HelperUITests.swift; sourceTree = ""; }; + 69E961DE27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift; sourceTree = ""; }; + 69E961E427E28B88008CF7C0 /* AluxLabs Link Safari Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "AluxLabs Link Safari Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 69E961E927E28B88008CF7C0 /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = ""; }; 69E961EC27E28B88008CF7C0 /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = _locales; sourceTree = ""; }; 69E961EE27E28B88008CF7C0 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; path = images; sourceTree = ""; }; 69E961F027E28B88008CF7C0 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = manifest.json; sourceTree = ""; }; - 69E961F227E28B88008CF7C0 /* scratch-link-extension.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "scratch-link-extension.js"; sourceTree = ""; }; - 69E961F427E28B88008CF7C0 /* scratch-link-extension-background.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "scratch-link-extension-background.js"; sourceTree = ""; }; + 69E961F227E28B88008CF7C0 /* aluxlabs-link-extension.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "aluxlabs-link-extension.js"; sourceTree = ""; }; + 69E961F427E28B88008CF7C0 /* aluxlabs-link-extension-background.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "aluxlabs-link-extension-background.js"; sourceTree = ""; }; 69E961FC27E28B88008CF7C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 69E961FD27E28B88008CF7C0 /* Scratch_Link_Safari_Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Scratch_Link_Safari_Extension.entitlements; sourceTree = ""; }; - 69FCB6DF28E750C400F753E6 /* ScratchLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScratchLog.swift; sourceTree = ""; }; + 69E961FD27E28B88008CF7C0 /* AluxLabs_Link_Safari_Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AluxLabs_Link_Safari_Extension.entitlements; sourceTree = ""; }; + 69FCB6DF28E750C400F753E6 /* AluxLabsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AluxLabsLog.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -161,10 +161,10 @@ children = ( 69C52B2527ECCB57006A46F3 /* Safari WebExtension messaging.md */, 699401DA289DA5F300A46D3F /* Configuration Files */, - 69E961B427E28B86008CF7C0 /* Scratch Link Safari Helper */, - 69E961D127E28B88008CF7C0 /* Scratch Link Safari HelperTests */, - 69E961DB27E28B88008CF7C0 /* Scratch Link Safari HelperUITests */, - 69E961E827E28B88008CF7C0 /* Scratch Link Safari Extension */, + 69E961B427E28B86008CF7C0 /* AluxLabs Link Safari Helper */, + 69E961D127E28B88008CF7C0 /* AluxLabs Link Safari HelperTests */, + 69E961DB27E28B88008CF7C0 /* AluxLabs Link Safari HelperUITests */, + 69E961E827E28B88008CF7C0 /* AluxLabs Link Safari Extension */, 69E961B327E28B86008CF7C0 /* Products */, ); sourceTree = ""; @@ -172,26 +172,26 @@ 69E961B327E28B86008CF7C0 /* Products */ = { isa = PBXGroup; children = ( - 69E961B227E28B86008CF7C0 /* Scratch Link Safari Helper.app */, - 69E961CE27E28B88008CF7C0 /* Scratch Link Safari HelperTests.xctest */, - 69E961D827E28B88008CF7C0 /* Scratch Link Safari HelperUITests.xctest */, - 69E961E427E28B88008CF7C0 /* Scratch Link Safari Extension.appex */, + 69E961B227E28B86008CF7C0 /* AluxLabs Link Safari Helper.app */, + 69E961CE27E28B88008CF7C0 /* AluxLabs Link Safari HelperTests.xctest */, + 69E961D827E28B88008CF7C0 /* AluxLabs Link Safari HelperUITests.xctest */, + 69E961E427E28B88008CF7C0 /* AluxLabs Link Safari Extension.appex */, ); name = Products; sourceTree = ""; }; - 69E961B427E28B86008CF7C0 /* Scratch Link Safari Helper */ = { + 69E961B427E28B86008CF7C0 /* AluxLabs Link Safari Helper */ = { isa = PBXGroup; children = ( 69E961B527E28B86008CF7C0 /* AppDelegate.swift */, 69E961C127E28B86008CF7C0 /* ViewController.swift */, 69E961C327E28B86008CF7C0 /* Main.storyboard */, 69E961C627E28B88008CF7C0 /* Assets.xcassets */, - 69E961C827E28B88008CF7C0 /* Scratch_Link_Safari_Helper.entitlements */, - 69E961C927E28B88008CF7C0 /* Scratch Link Safari Helper.entitlements */, + 69E961C827E28B88008CF7C0 /* AluxLabs_Link_Safari_Helper.entitlements */, + 69E961C927E28B88008CF7C0 /* AluxLabs Link Safari Helper.entitlements */, 69E961B727E28B86008CF7C0 /* Resources */, ); - path = "Scratch Link Safari Helper"; + path = "AluxLabs Link Safari Helper"; sourceTree = ""; }; 69E961B727E28B86008CF7C0 /* Resources */ = { @@ -205,37 +205,37 @@ path = Resources; sourceTree = ""; }; - 69E961D127E28B88008CF7C0 /* Scratch Link Safari HelperTests */ = { + 69E961D127E28B88008CF7C0 /* AluxLabs Link Safari HelperTests */ = { isa = PBXGroup; children = ( - 69E961D227E28B88008CF7C0 /* Scratch_Link_Safari_HelperTests.swift */, + 69E961D227E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperTests.swift */, ); - path = "Scratch Link Safari HelperTests"; + path = "AluxLabs Link Safari HelperTests"; sourceTree = ""; }; - 69E961DB27E28B88008CF7C0 /* Scratch Link Safari HelperUITests */ = { + 69E961DB27E28B88008CF7C0 /* AluxLabs Link Safari HelperUITests */ = { isa = PBXGroup; children = ( - 69E961DC27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITests.swift */, - 69E961DE27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITestsLaunchTests.swift */, + 69E961DC27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITests.swift */, + 69E961DE27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift */, ); - path = "Scratch Link Safari HelperUITests"; + path = "AluxLabs Link Safari HelperUITests"; sourceTree = ""; }; - 69E961E827E28B88008CF7C0 /* Scratch Link Safari Extension */ = { + 69E961E827E28B88008CF7C0 /* AluxLabs Link Safari Extension */ = { isa = PBXGroup; children = ( 69E1236228A3536800F6AAD5 /* Makefile */, 69C52B3027F50E57006A46F3 /* JSON.swift */, 69E961E927E28B88008CF7C0 /* SafariWebExtensionHandler.swift */, - 69FCB6DF28E750C400F753E6 /* ScratchLog.swift */, + 69FCB6DF28E750C400F753E6 /* AluxLabsLog.swift */, 69C52B2E27F502F2006A46F3 /* SessionDelegate.swift */, 69E961FC27E28B88008CF7C0 /* Info.plist */, - 69E961FD27E28B88008CF7C0 /* Scratch_Link_Safari_Extension.entitlements */, + 69E961FD27E28B88008CF7C0 /* AluxLabs_Link_Safari_Extension.entitlements */, 69E961EB27E28B88008CF7C0 /* Resources */, 694C924028C90B2A00182C58 /* inject-version-info.sh */, ); - path = "Scratch Link Safari Extension"; + path = "AluxLabs Link Safari Extension"; sourceTree = ""; }; 69E961EB27E28B88008CF7C0 /* Resources */ = { @@ -245,8 +245,8 @@ 69E961EC27E28B88008CF7C0 /* _locales */, 69E961EE27E28B88008CF7C0 /* images */, 69E961F027E28B88008CF7C0 /* manifest.json */, - 69E961F227E28B88008CF7C0 /* scratch-link-extension.js */, - 69E961F427E28B88008CF7C0 /* scratch-link-extension-background.js */, + 69E961F227E28B88008CF7C0 /* aluxlabs-link-extension.js */, + 69E961F427E28B88008CF7C0 /* aluxlabs-link-extension-background.js */, ); path = Resources; sourceTree = ""; @@ -254,9 +254,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 69E961B127E28B86008CF7C0 /* Scratch Link Safari Helper */ = { + 69E961B127E28B86008CF7C0 /* AluxLabs Link Safari Helper */ = { isa = PBXNativeTarget; - buildConfigurationList = 69E9620427E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari Helper" */; + buildConfigurationList = 69E9620427E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari Helper" */; buildPhases = ( 69E961AE27E28B86008CF7C0 /* Sources */, 69E961AF27E28B86008CF7C0 /* Frameworks */, @@ -268,14 +268,14 @@ dependencies = ( 69E961E727E28B88008CF7C0 /* PBXTargetDependency */, ); - name = "Scratch Link Safari Helper"; - productName = "Scratch Link Safari Helper"; - productReference = 69E961B227E28B86008CF7C0 /* Scratch Link Safari Helper.app */; + name = "AluxLabs Link Safari Helper"; + productName = "AluxLabs Link Safari Helper"; + productReference = 69E961B227E28B86008CF7C0 /* AluxLabs Link Safari Helper.app */; productType = "com.apple.product-type.application"; }; - 69E961CD27E28B88008CF7C0 /* Scratch Link Safari HelperTests */ = { + 69E961CD27E28B88008CF7C0 /* AluxLabs Link Safari HelperTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 69E9620727E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari HelperTests" */; + buildConfigurationList = 69E9620727E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari HelperTests" */; buildPhases = ( 69E961CA27E28B88008CF7C0 /* Sources */, 69E961CB27E28B88008CF7C0 /* Frameworks */, @@ -286,14 +286,14 @@ dependencies = ( 69E961D027E28B88008CF7C0 /* PBXTargetDependency */, ); - name = "Scratch Link Safari HelperTests"; - productName = "Scratch Link Safari HelperTests"; - productReference = 69E961CE27E28B88008CF7C0 /* Scratch Link Safari HelperTests.xctest */; + name = "AluxLabs Link Safari HelperTests"; + productName = "AluxLabs Link Safari HelperTests"; + productReference = 69E961CE27E28B88008CF7C0 /* AluxLabs Link Safari HelperTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 69E961D727E28B88008CF7C0 /* Scratch Link Safari HelperUITests */ = { + 69E961D727E28B88008CF7C0 /* AluxLabs Link Safari HelperUITests */ = { isa = PBXNativeTarget; - buildConfigurationList = 69E9620A27E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari HelperUITests" */; + buildConfigurationList = 69E9620A27E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari HelperUITests" */; buildPhases = ( 69E961D427E28B88008CF7C0 /* Sources */, 69E961D527E28B88008CF7C0 /* Frameworks */, @@ -304,14 +304,14 @@ dependencies = ( 69E961DA27E28B88008CF7C0 /* PBXTargetDependency */, ); - name = "Scratch Link Safari HelperUITests"; - productName = "Scratch Link Safari HelperUITests"; - productReference = 69E961D827E28B88008CF7C0 /* Scratch Link Safari HelperUITests.xctest */; + name = "AluxLabs Link Safari HelperUITests"; + productName = "AluxLabs Link Safari HelperUITests"; + productReference = 69E961D827E28B88008CF7C0 /* AluxLabs Link Safari HelperUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; - 69E961E327E28B88008CF7C0 /* Scratch Link Safari Extension */ = { + 69E961E327E28B88008CF7C0 /* AluxLabs Link Safari Extension */ = { isa = PBXNativeTarget; - buildConfigurationList = 69E9620027E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari Extension" */; + buildConfigurationList = 69E9620027E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari Extension" */; buildPhases = ( 69E961E027E28B88008CF7C0 /* Sources */, 69E961E127E28B88008CF7C0 /* Frameworks */, @@ -322,9 +322,9 @@ ); dependencies = ( ); - name = "Scratch Link Safari Extension"; - productName = "Scratch Link Safari Extension"; - productReference = 69E961E427E28B88008CF7C0 /* Scratch Link Safari Extension.appex */; + name = "AluxLabs Link Safari Extension"; + productName = "AluxLabs Link Safari Extension"; + productReference = 69E961E427E28B88008CF7C0 /* AluxLabs Link Safari Extension.appex */; productType = "com.apple.product-type.app-extension"; }; /* End PBXNativeTarget section */ @@ -353,7 +353,7 @@ }; }; }; - buildConfigurationList = 69E961AD27E28B86008CF7C0 /* Build configuration list for PBXProject "Scratch Link Safari Helper" */; + buildConfigurationList = 69E961AD27E28B86008CF7C0 /* Build configuration list for PBXProject "AluxLabs Link Safari Helper" */; compatibilityVersion = "Xcode 13.0"; developmentRegion = en; hasScannedForEncodings = 0; @@ -366,10 +366,10 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 69E961B127E28B86008CF7C0 /* Scratch Link Safari Helper */, - 69E961CD27E28B88008CF7C0 /* Scratch Link Safari HelperTests */, - 69E961D727E28B88008CF7C0 /* Scratch Link Safari HelperUITests */, - 69E961E327E28B88008CF7C0 /* Scratch Link Safari Extension */, + 69E961B127E28B86008CF7C0 /* AluxLabs Link Safari Helper */, + 69E961CD27E28B88008CF7C0 /* AluxLabs Link Safari HelperTests */, + 69E961D727E28B88008CF7C0 /* AluxLabs Link Safari HelperUITests */, + 69E961E327E28B88008CF7C0 /* AluxLabs Link Safari Extension */, ); }; /* End PBXProject section */ @@ -406,11 +406,11 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 69E961F327E28B88008CF7C0 /* scratch-link-extension.js in Resources */, + 69E961F327E28B88008CF7C0 /* aluxlabs-link-extension.js in Resources */, 69E961EF27E28B88008CF7C0 /* images in Resources */, 69E1236628A40EC000F6AAD5 /* web in Resources */, 69E961ED27E28B88008CF7C0 /* _locales in Resources */, - 69E961F527E28B88008CF7C0 /* scratch-link-extension-background.js in Resources */, + 69E961F527E28B88008CF7C0 /* aluxlabs-link-extension-background.js in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -453,7 +453,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 69E961D327E28B88008CF7C0 /* Scratch_Link_Safari_HelperTests.swift in Sources */, + 69E961D327E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -461,8 +461,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 69E961DD27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITests.swift in Sources */, - 69E961DF27E28B88008CF7C0 /* Scratch_Link_Safari_HelperUITestsLaunchTests.swift in Sources */, + 69E961DD27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITests.swift in Sources */, + 69E961DF27E28B88008CF7C0 /* AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -471,7 +471,7 @@ buildActionMask = 2147483647; files = ( 69E961EA27E28B88008CF7C0 /* SafariWebExtensionHandler.swift in Sources */, - 69FCB6E028E750C400F753E6 /* ScratchLog.swift in Sources */, + 69FCB6E028E750C400F753E6 /* AluxLabsLog.swift in Sources */, 69C52B3127F50E57006A46F3 /* JSON.swift in Sources */, 69C52B2F27F502F2006A46F3 /* SessionDelegate.swift in Sources */, ); @@ -482,17 +482,17 @@ /* Begin PBXTargetDependency section */ 69E961D027E28B88008CF7C0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 69E961B127E28B86008CF7C0 /* Scratch Link Safari Helper */; + target = 69E961B127E28B86008CF7C0 /* AluxLabs Link Safari Helper */; targetProxy = 69E961CF27E28B88008CF7C0 /* PBXContainerItemProxy */; }; 69E961DA27E28B88008CF7C0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 69E961B127E28B86008CF7C0 /* Scratch Link Safari Helper */; + target = 69E961B127E28B86008CF7C0 /* AluxLabs Link Safari Helper */; targetProxy = 69E961D927E28B88008CF7C0 /* PBXContainerItemProxy */; }; 69E961E727E28B88008CF7C0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 69E961E327E28B88008CF7C0 /* Scratch Link Safari Extension */; + target = 69E961E327E28B88008CF7C0 /* AluxLabs Link Safari Extension */; targetProxy = 69E961E627E28B88008CF7C0 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -577,11 +577,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Helper/Scratch Link Safari Helper.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.entitlements"; COMBINE_HIDPI_IMAGES = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Helper"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Helper"; INFOPLIST_KEY_NSMainStoryboardFile = Main; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( @@ -594,7 +594,7 @@ "-framework", WebKit, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; }; @@ -607,10 +607,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.tests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Scratch Link Safari Helper.app/Contents/MacOS/Scratch Link Safari Helper"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AluxLabs Link Safari Helper.app/Contents/MacOS/AluxLabs Link Safari Helper"; }; name = Release_MAS; }; @@ -620,10 +620,10 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.uitests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.uitests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_TARGET_NAME = "Scratch Link Safari Helper"; + TEST_TARGET_NAME = "AluxLabs Link Safari Helper"; }; name = Release_MAS; }; @@ -631,11 +631,11 @@ isa = XCBuildConfiguration; baseConfigurationReference = 699401DD289DA67700A46D3F /* Release_MAS.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Extension/Scratch_Link_Safari_Extension.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Extension/AluxLabs_Link_Safari_Extension.entitlements"; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Scratch Link Safari Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Extension"; + INFOPLIST_FILE = "AluxLabs Link Safari Extension/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Extension"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -645,7 +645,7 @@ "-framework", SafariServices, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-extension"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -712,11 +712,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Helper/Scratch Link Safari Helper.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.entitlements"; COMBINE_HIDPI_IMAGES = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Helper"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Helper"; INFOPLIST_KEY_NSMainStoryboardFile = Main; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( @@ -729,7 +729,7 @@ "-framework", WebKit, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; }; @@ -742,10 +742,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.tests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Scratch Link Safari Helper.app/Contents/MacOS/Scratch Link Safari Helper"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AluxLabs Link Safari Helper.app/Contents/MacOS/AluxLabs Link Safari Helper"; }; name = Release_DevID; }; @@ -755,10 +755,10 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.uitests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.uitests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_TARGET_NAME = "Scratch Link Safari Helper"; + TEST_TARGET_NAME = "AluxLabs Link Safari Helper"; }; name = Release_DevID; }; @@ -766,11 +766,11 @@ isa = XCBuildConfiguration; baseConfigurationReference = 699401DC289DA65C00A46D3F /* Release_DevID.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Extension/Scratch_Link_Safari_Extension.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Extension/AluxLabs_Link_Safari_Extension.entitlements"; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Scratch Link Safari Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Extension"; + INFOPLIST_FILE = "AluxLabs Link Safari Extension/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Extension"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -780,7 +780,7 @@ "-framework", SafariServices, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-extension"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -897,11 +897,11 @@ isa = XCBuildConfiguration; baseConfigurationReference = 699401D9289DA5E600A46D3F /* Debug.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Extension/Scratch_Link_Safari_Extension.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Extension/AluxLabs_Link_Safari_Extension.entitlements"; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Scratch Link Safari Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Extension"; + INFOPLIST_FILE = "AluxLabs Link Safari Extension/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Extension"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -911,7 +911,7 @@ "-framework", SafariServices, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-extension"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -922,11 +922,11 @@ isa = XCBuildConfiguration; baseConfigurationReference = 699401DB289DA64100A46D3F /* Release.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Extension/Scratch_Link_Safari_Extension.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Extension/AluxLabs_Link_Safari_Extension.entitlements"; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Scratch Link Safari Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Extension"; + INFOPLIST_FILE = "AluxLabs Link Safari Extension/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Extension"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -936,7 +936,7 @@ "-framework", SafariServices, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-extension"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -950,11 +950,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Helper/Scratch Link Safari Helper.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.entitlements"; COMBINE_HIDPI_IMAGES = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Helper"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Helper"; INFOPLIST_KEY_NSMainStoryboardFile = Main; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( @@ -967,7 +967,7 @@ "-framework", WebKit, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; }; @@ -980,11 +980,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = "Scratch Link Safari Helper/Scratch Link Safari Helper.entitlements"; + CODE_SIGN_ENTITLEMENTS = "AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.entitlements"; COMBINE_HIDPI_IMAGES = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = "Scratch Link Safari Helper"; + INFOPLIST_KEY_CFBundleDisplayName = "AluxLabs Link Safari Helper"; INFOPLIST_KEY_NSMainStoryboardFile = Main; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( @@ -997,7 +997,7 @@ "-framework", WebKit, ); - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; }; @@ -1010,10 +1010,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.tests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Scratch Link Safari Helper.app/Contents/MacOS/Scratch Link Safari Helper"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AluxLabs Link Safari Helper.app/Contents/MacOS/AluxLabs Link Safari Helper"; }; name = Debug; }; @@ -1024,10 +1024,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.tests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Scratch Link Safari Helper.app/Contents/MacOS/Scratch Link Safari Helper"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AluxLabs Link Safari Helper.app/Contents/MacOS/AluxLabs Link Safari Helper"; }; name = Release; }; @@ -1037,10 +1037,10 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.uitests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.uitests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_TARGET_NAME = "Scratch Link Safari Helper"; + TEST_TARGET_NAME = "AluxLabs Link Safari Helper"; }; name = Debug; }; @@ -1050,17 +1050,17 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; GENERATE_INFOPLIST_FILE = YES; - PRODUCT_BUNDLE_IDENTIFIER = "edu.mit.scratch.scratch-link.safari-helper.uitests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.aluxlabs.link.safari-helper.uitests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; - TEST_TARGET_NAME = "Scratch Link Safari Helper"; + TEST_TARGET_NAME = "AluxLabs Link Safari Helper"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 69E961AD27E28B86008CF7C0 /* Build configuration list for PBXProject "Scratch Link Safari Helper" */ = { + 69E961AD27E28B86008CF7C0 /* Build configuration list for PBXProject "AluxLabs Link Safari Helper" */ = { isa = XCConfigurationList; buildConfigurations = ( 69E961FE27E28B88008CF7C0 /* Debug */, @@ -1071,7 +1071,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - 69E9620027E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari Extension" */ = { + 69E9620027E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari Extension" */ = { isa = XCConfigurationList; buildConfigurations = ( 69E9620127E28B88008CF7C0 /* Debug */, @@ -1082,7 +1082,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - 69E9620427E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari Helper" */ = { + 69E9620427E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari Helper" */ = { isa = XCConfigurationList; buildConfigurations = ( 69E9620527E28B88008CF7C0 /* Debug */, @@ -1093,7 +1093,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - 69E9620727E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari HelperTests" */ = { + 69E9620727E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari HelperTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 69E9620827E28B88008CF7C0 /* Debug */, @@ -1104,7 +1104,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - 69E9620A27E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "Scratch Link Safari HelperUITests" */ = { + 69E9620A27E28B88008CF7C0 /* Build configuration list for PBXNativeTarget "AluxLabs Link Safari HelperUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( 69E9620B27E28B88008CF7C0 /* Debug */, diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/xcshareddata/xcschemes/Scratch Link Safari Helper.xcscheme b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/xcshareddata/xcschemes/AluxLabs Link Safari Helper.xcscheme similarity index 73% rename from Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/xcshareddata/xcschemes/Scratch Link Safari Helper.xcscheme rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/xcshareddata/xcschemes/AluxLabs Link Safari Helper.xcscheme index 56655b44..3a8a3d07 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Helper.xcodeproj/xcshareddata/xcschemes/Scratch Link Safari Helper.xcscheme +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.xcodeproj/xcshareddata/xcschemes/AluxLabs Link Safari Helper.xcscheme @@ -15,9 +15,9 @@ + BuildableName = "AluxLabs Link Safari Helper.app" + BlueprintName = "AluxLabs Link Safari Helper" + ReferencedContainer = "container:AluxLabs Link Safari Helper.xcodeproj"> @@ -33,9 +33,9 @@ + BuildableName = "AluxLabs Link Safari HelperTests.xctest" + BlueprintName = "AluxLabs Link Safari HelperTests" + ReferencedContainer = "container:AluxLabs Link Safari Helper.xcodeproj"> + BuildableName = "AluxLabs Link Safari HelperUITests.xctest" + BlueprintName = "AluxLabs Link Safari HelperUITests" + ReferencedContainer = "container:AluxLabs Link Safari Helper.xcodeproj"> @@ -65,9 +65,9 @@ + BuildableName = "AluxLabs Link Safari Helper.app" + BlueprintName = "AluxLabs Link Safari Helper" + ReferencedContainer = "container:AluxLabs Link Safari Helper.xcodeproj"> @@ -82,9 +82,9 @@ + BuildableName = "AluxLabs Link Safari Helper.app" + BlueprintName = "AluxLabs Link Safari Helper" + ReferencedContainer = "container:AluxLabs Link Safari Helper.xcodeproj"> diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Scratch Link Safari Helper.entitlements b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.entitlements similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Scratch Link Safari Helper.entitlements rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper.entitlements diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Scratch_Link_Safari_Helper.entitlements b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/AluxLabs_Link_Safari_Helper.entitlements similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Scratch_Link_Safari_Helper.entitlements rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/AluxLabs_Link_Safari_Helper.entitlements diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/AppDelegate.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/AppDelegate.swift similarity index 93% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/AppDelegate.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/AppDelegate.swift index 05f756b3..2628cf1a 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Helper/AppDelegate.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/AppDelegate.swift @@ -1,6 +1,6 @@ // // AppDelegate.swift -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 3/16/22. // diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/AccentColor.colorset/Contents.json b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/AccentColor.colorset/Contents.json rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/AppIcon.appiconset/Contents.json b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/AppIcon.appiconset/Contents.json rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/Contents.json b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/Contents.json similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/Contents.json rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/Contents.json diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/LargeIcon.imageset/Contents.json b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/LargeIcon.imageset/Contents.json similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Assets.xcassets/LargeIcon.imageset/Contents.json rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Assets.xcassets/LargeIcon.imageset/Contents.json diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Base.lproj/Main.html b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Base.lproj/Main.html similarity index 50% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Base.lproj/Main.html rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Base.lproj/Main.html index 3dc19919..28c4f53c 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Helper/Base.lproj/Main.html +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Base.lproj/Main.html @@ -10,10 +10,10 @@ - Scratch Link Safari Helper Icon -

You can turn on Scratch Link Safari Helper’s extension in Safari Extensions preferences.

-

Scratch Link Safari Helper’s extension is currently on. You can turn it off in Safari Extensions preferences.

-

Scratch Link Safari Helper’s extension is currently off. You can turn it on in Safari Extensions preferences.

+ AluxLabs Link Safari Helper Icon +

You can turn on AluxLabs Link Safari Helper’s extension in Safari Extensions preferences.

+

AluxLabs Link Safari Helper’s extension is currently on. You can turn it off in Safari Extensions preferences.

+

AluxLabs Link Safari Helper’s extension is currently off. You can turn it on in Safari Extensions preferences.

diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Base.lproj/Main.storyboard b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Base.lproj/Main.storyboard similarity index 88% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Base.lproj/Main.storyboard rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Base.lproj/Main.storyboard index 4073c9bd..97e01f2d 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Helper/Base.lproj/Main.storyboard +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Base.lproj/Main.storyboard @@ -12,18 +12,18 @@ - + - + - + - + @@ -41,7 +41,7 @@ - + @@ -53,7 +53,7 @@ - + @@ -77,7 +77,7 @@ - + diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Resources/Icon.png b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Resources/Icon.png similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Resources/Icon.png rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Resources/Icon.png diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Resources/Script.js b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Resources/Script.js similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Resources/Script.js rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Resources/Script.js diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/Resources/Style.css b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Resources/Style.css similarity index 100% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/Resources/Style.css rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/Resources/Style.css diff --git a/Scratch Link Safari Helper/Scratch Link Safari Helper/ViewController.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/ViewController.swift similarity index 93% rename from Scratch Link Safari Helper/Scratch Link Safari Helper/ViewController.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/ViewController.swift index cbb8101b..1848f0af 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari Helper/ViewController.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari Helper/ViewController.swift @@ -1,6 +1,6 @@ // // ViewController.swift -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 3/16/22. // @@ -9,7 +9,7 @@ import Cocoa import SafariServices import WebKit -let extensionBundleIdentifier = "edu.mit.scratch.scratch-link.safari-extension" +let extensionBundleIdentifier = "com.aluxlabs.link.safari-extension" class ViewController: NSViewController, WKNavigationDelegate, WKScriptMessageHandler { diff --git a/Scratch Link Safari Helper/Scratch Link Safari HelperTests/Scratch_Link_Safari_HelperTests.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari HelperTests/AluxLabs_Link_Safari_HelperTests.swift similarity index 86% rename from Scratch Link Safari Helper/Scratch Link Safari HelperTests/Scratch_Link_Safari_HelperTests.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari HelperTests/AluxLabs_Link_Safari_HelperTests.swift index 5f256f3a..c570b2de 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari HelperTests/Scratch_Link_Safari_HelperTests.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari HelperTests/AluxLabs_Link_Safari_HelperTests.swift @@ -1,14 +1,14 @@ // -// Scratch_Link_Safari_HelperTests.swift -// Scratch Link Safari HelperTests +// AluxLabs_Link_Safari_HelperTests.swift +// AluxLabs Link Safari HelperTests // // Created by Christopher Willis-Ford on 3/16/22. // import XCTest -@testable import Scratch_Link_Safari_Helper +@testable import AluxLabs_Link_Safari_Helper -class Scratch_Link_Safari_HelperTests: XCTestCase { +class AluxLabs_Link_Safari_HelperTests: XCTestCase { override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. diff --git a/Scratch Link Safari Helper/Scratch Link Safari HelperUITests/Scratch_Link_Safari_HelperUITests.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari HelperUITests/AluxLabs_Link_Safari_HelperUITests.swift similarity index 90% rename from Scratch Link Safari Helper/Scratch Link Safari HelperUITests/Scratch_Link_Safari_HelperUITests.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari HelperUITests/AluxLabs_Link_Safari_HelperUITests.swift index eaf3c056..b606ba77 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari HelperUITests/Scratch_Link_Safari_HelperUITests.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari HelperUITests/AluxLabs_Link_Safari_HelperUITests.swift @@ -1,13 +1,13 @@ // -// Scratch_Link_Safari_HelperUITests.swift -// Scratch Link Safari HelperUITests +// AluxLabs_Link_Safari_HelperUITests.swift +// AluxLabs Link Safari HelperUITests // // Created by Christopher Willis-Ford on 3/16/22. // import XCTest -class Scratch_Link_Safari_HelperUITests: XCTestCase { +class AluxLabs_Link_Safari_HelperUITests: XCTestCase { override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. diff --git a/Scratch Link Safari Helper/Scratch Link Safari HelperUITests/Scratch_Link_Safari_HelperUITestsLaunchTests.swift b/AluxLabs Link Safari Helper/AluxLabs Link Safari HelperUITests/AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift similarity index 81% rename from Scratch Link Safari Helper/Scratch Link Safari HelperUITests/Scratch_Link_Safari_HelperUITestsLaunchTests.swift rename to AluxLabs Link Safari Helper/AluxLabs Link Safari HelperUITests/AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift index b994df8b..e2bac207 100644 --- a/Scratch Link Safari Helper/Scratch Link Safari HelperUITests/Scratch_Link_Safari_HelperUITestsLaunchTests.swift +++ b/AluxLabs Link Safari Helper/AluxLabs Link Safari HelperUITests/AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift @@ -1,13 +1,13 @@ // -// Scratch_Link_Safari_HelperUITestsLaunchTests.swift -// Scratch Link Safari HelperUITests +// AluxLabs_Link_Safari_HelperUITestsLaunchTests.swift +// AluxLabs Link Safari HelperUITests // // Created by Christopher Willis-Ford on 3/16/22. // import XCTest -class Scratch_Link_Safari_HelperUITestsLaunchTests: XCTestCase { +class AluxLabs_Link_Safari_HelperUITestsLaunchTests: XCTestCase { override class var runsForEachTargetApplicationUIConfiguration: Bool { true diff --git a/Scratch Link Safari Helper/Configuration Files/All Configurations.xcconfig b/AluxLabs Link Safari Helper/Configuration Files/All Configurations.xcconfig similarity index 90% rename from Scratch Link Safari Helper/Configuration Files/All Configurations.xcconfig rename to AluxLabs Link Safari Helper/Configuration Files/All Configurations.xcconfig index a4928ed0..4123717b 100644 --- a/Scratch Link Safari Helper/Configuration Files/All Configurations.xcconfig +++ b/AluxLabs Link Safari Helper/Configuration Files/All Configurations.xcconfig @@ -1,6 +1,6 @@ // // All Configurations.xcconfig -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 8/5/22. // diff --git a/Scratch Link Safari Helper/Configuration Files/Debug.xcconfig b/AluxLabs Link Safari Helper/Configuration Files/Debug.xcconfig similarity index 95% rename from Scratch Link Safari Helper/Configuration Files/Debug.xcconfig rename to AluxLabs Link Safari Helper/Configuration Files/Debug.xcconfig index 7c297307..5e8a4688 100644 --- a/Scratch Link Safari Helper/Configuration Files/Debug.xcconfig +++ b/AluxLabs Link Safari Helper/Configuration Files/Debug.xcconfig @@ -1,6 +1,6 @@ // // Debug.xcconfig -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 8/5/22. // diff --git a/Scratch Link Safari Helper/Configuration Files/Release.xcconfig b/AluxLabs Link Safari Helper/Configuration Files/Release.xcconfig similarity index 93% rename from Scratch Link Safari Helper/Configuration Files/Release.xcconfig rename to AluxLabs Link Safari Helper/Configuration Files/Release.xcconfig index b2c9788b..166d6816 100644 --- a/Scratch Link Safari Helper/Configuration Files/Release.xcconfig +++ b/AluxLabs Link Safari Helper/Configuration Files/Release.xcconfig @@ -1,6 +1,6 @@ // // Release.xcconfig -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 8/5/22. // diff --git a/Scratch Link Safari Helper/Configuration Files/Release_DevID.xcconfig b/AluxLabs Link Safari Helper/Configuration Files/Release_DevID.xcconfig similarity index 70% rename from Scratch Link Safari Helper/Configuration Files/Release_DevID.xcconfig rename to AluxLabs Link Safari Helper/Configuration Files/Release_DevID.xcconfig index 6fdb93d4..3a6d9509 100644 --- a/Scratch Link Safari Helper/Configuration Files/Release_DevID.xcconfig +++ b/AluxLabs Link Safari Helper/Configuration Files/Release_DevID.xcconfig @@ -1,6 +1,6 @@ // // Release_DevID.xcconfig -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 8/5/22. // @@ -12,4 +12,4 @@ #include "Shipping.xcconfig" CODE_SIGN_IDENTITY = Developer ID Application; -PROVISIONING_PROFILE_SPECIFIER = match Direct edu.mit.scratch.scratch-link.safari-extension macos; +PROVISIONING_PROFILE_SPECIFIER = match Direct com.aluxlabs.link.safari-extension macos; diff --git a/Scratch Link Safari Helper/Configuration Files/Release_MAS.xcconfig b/AluxLabs Link Safari Helper/Configuration Files/Release_MAS.xcconfig similarity index 69% rename from Scratch Link Safari Helper/Configuration Files/Release_MAS.xcconfig rename to AluxLabs Link Safari Helper/Configuration Files/Release_MAS.xcconfig index 70e66510..82ce7ce2 100644 --- a/Scratch Link Safari Helper/Configuration Files/Release_MAS.xcconfig +++ b/AluxLabs Link Safari Helper/Configuration Files/Release_MAS.xcconfig @@ -1,6 +1,6 @@ // // Release_MAS.xcconfig -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 8/5/22. // @@ -12,4 +12,4 @@ #include "Shipping.xcconfig" CODE_SIGN_IDENTITY = Apple Distribution; -PROVISIONING_PROFILE_SPECIFIER = match AppStore edu.mit.scratch.scratch-link.safari-extension macos; +PROVISIONING_PROFILE_SPECIFIER = match AppStore com.aluxlabs.link.safari-extension macos; diff --git a/Scratch Link Safari Helper/Configuration Files/Shipping.xcconfig b/AluxLabs Link Safari Helper/Configuration Files/Shipping.xcconfig similarity index 84% rename from Scratch Link Safari Helper/Configuration Files/Shipping.xcconfig rename to AluxLabs Link Safari Helper/Configuration Files/Shipping.xcconfig index c0d26646..f0f2cf20 100644 --- a/Scratch Link Safari Helper/Configuration Files/Shipping.xcconfig +++ b/AluxLabs Link Safari Helper/Configuration Files/Shipping.xcconfig @@ -1,6 +1,6 @@ // // Shipping.xcconfig -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 8/5/22. // @@ -11,7 +11,7 @@ // Enable secure timestamp for code signing OTHER_CODE_SIGN_FLAGS = --timestamp $(inherited); -PRODUCT_BUNDLE_IDENTIFIER = edu.mit.scratch.scratch-link.safari-extension; +PRODUCT_BUNDLE_IDENTIFIER = com.aluxlabs.link.safari-extension; DEVELOPMENT_TEAM = W7AR3WMP87; // Setting this to NO will prevent injection of the "com.apple.security.get-task-allow" entitlement diff --git a/Scratch Link Safari Helper/Configuration Files/Version.xcconfig b/AluxLabs Link Safari Helper/Configuration Files/Version.xcconfig similarity index 91% rename from Scratch Link Safari Helper/Configuration Files/Version.xcconfig rename to AluxLabs Link Safari Helper/Configuration Files/Version.xcconfig index 487e9a87..f070e1a3 100644 --- a/Scratch Link Safari Helper/Configuration Files/Version.xcconfig +++ b/AluxLabs Link Safari Helper/Configuration Files/Version.xcconfig @@ -1,6 +1,6 @@ // // Version.xcconfig -// Scratch Link Safari Helper +// AluxLabs Link Safari Helper // // Created by Christopher Willis-Ford on 8/5/22. // diff --git a/Scratch Link Safari Helper/Safari WebExtension messaging.md b/AluxLabs Link Safari Helper/Safari WebExtension messaging.md similarity index 95% rename from Scratch Link Safari Helper/Safari WebExtension messaging.md rename to AluxLabs Link Safari Helper/Safari WebExtension messaging.md index 8a89e2e2..960974d7 100644 --- a/Scratch Link Safari Helper/Safari WebExtension messaging.md +++ b/AluxLabs Link Safari Helper/Safari WebExtension messaging.md @@ -1,6 +1,6 @@ # Safari WebExtension messaging -The Scratch Link Safari Helper uses Safari's version of the WebExtension API. Communication between components is +The AluxLabs Link Safari Helper uses Safari's version of the WebExtension API. Communication between components is restricted and each component has its own set of communication channels. The components and communication channels are documented here to help make sense of the spaghetti. @@ -20,7 +20,7 @@ The components involved in extension communication include: `NSExtensionRequestHandling` Objective-C protocol. Safari's WebExtension implementation requires that an extension be hosted by a native application -- in this case, -Scratch Link. There are Safari-specific ways to communicate between the WebExtension and its host app, but Scratch +AluxLabs Link. There are Safari-specific ways to communicate between the WebExtension and its host app, but Scratch Link does not use those so they're not covered here. ```mermaid diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 43748a8b..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,497 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. See -[Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# [2.1.0-develop.10](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.9...v2.1.0-develop.10) (2023-09-25) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.10 ([911bbba](https:/home/circleci/project/semantic-release-remote/commit/911bbbab8a4ff484a450e688b5953a3fd3a4e7d3)) -* **deps:** update dependency scratch-vm to v1.6.11 ([5544897](https:/home/circleci/project/semantic-release-remote/commit/5544897487c66def49af50c1a07e65c75af86335)) -* **deps:** update dependency scratch-vm to v1.6.12 ([5948b02](https:/home/circleci/project/semantic-release-remote/commit/5948b02473773f33f581a9731a28f86a26612881)) -* **deps:** update dependency scratch-vm to v1.6.13 ([31bc061](https:/home/circleci/project/semantic-release-remote/commit/31bc061932429a387a607256d6a37355ea6bf6a2)) -* **deps:** update dependency scratch-vm to v1.6.14 ([1323ac0](https:/home/circleci/project/semantic-release-remote/commit/1323ac0d39ea4f68bcd0a39621cae87ce1e42507)) -* **deps:** update dependency scratch-vm to v1.6.15 ([9d9a801](https:/home/circleci/project/semantic-release-remote/commit/9d9a8014727aa23601e42292d3d6f423eb164f53)) -* **deps:** update dependency scratch-vm to v1.6.16 ([b2d429e](https:/home/circleci/project/semantic-release-remote/commit/b2d429e426416ebef6e32183df68fbae8dbb2c3c)) -* **deps:** update dependency scratch-vm to v1.6.17 ([239e35a](https:/home/circleci/project/semantic-release-remote/commit/239e35a28f27ce7686a36831cf8f098954e1a1be)) -* **deps:** update dependency scratch-vm to v1.6.18 ([9bb27fa](https:/home/circleci/project/semantic-release-remote/commit/9bb27fa0c5d5d74cc8d9e1486cb130fff27b7a74)) -* **deps:** update dependency scratch-vm to v1.6.19 ([8a72117](https:/home/circleci/project/semantic-release-remote/commit/8a7211749f93ad2b1b9f563dc19d8a109ab33090)) - -# [2.1.0-develop.9](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.8...v2.1.0-develop.9) (2023-09-09) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.9 ([d6db186](https:/home/circleci/project/semantic-release-remote/commit/d6db1861a274be97474a4a0a3f89ec4a51b2dde6)) - -# [2.1.0-develop.8](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.7...v2.1.0-develop.8) (2023-09-02) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.8 ([e0f852d](https:/home/circleci/project/semantic-release-remote/commit/e0f852d8eb165e93cb181cc36c84bd0c21ccb27a)) - -# [2.1.0-develop.7](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.6...v2.1.0-develop.7) (2023-08-30) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.7 ([21a5e3d](https:/home/circleci/project/semantic-release-remote/commit/21a5e3d69882a6f1f683d5b84ca4cde08b48cb10)) - -# [2.1.0-develop.6](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.5...v2.1.0-develop.6) (2023-08-28) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.6 ([9365bad](https:/home/circleci/project/semantic-release-remote/commit/9365bad80e094d09a55e12f0fc1cd299714745be)) - -# [2.1.0-develop.5](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.4...v2.1.0-develop.5) (2023-08-27) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.5 ([97159bb](https:/home/circleci/project/semantic-release-remote/commit/97159bbabae791f1848795765444b414221dfc9d)) - -# [2.1.0-develop.4](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.3...v2.1.0-develop.4) (2023-08-23) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.4 ([78f868b](https:/home/circleci/project/semantic-release-remote/commit/78f868b724a0e3bcc28e80f7d4e82965f461c95d)) - -# [2.1.0-develop.3](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.2...v2.1.0-develop.3) (2023-08-21) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.2 ([9cb3de7](https:/home/circleci/project/semantic-release-remote/commit/9cb3de7d5589a7e4b68e984655b5173dadabed24)) -* **deps:** update dependency scratch-vm to v1.6.3 ([c325210](https:/home/circleci/project/semantic-release-remote/commit/c325210a8c8cdf4f94896d39998bbddf2fc1b9f9)) - -# [2.1.0-develop.2](https:/home/circleci/project/semantic-release-remote/compare/v2.1.0-develop.1...v2.1.0-develop.2) (2023-08-09) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.6.1 ([eeba9f3](https:/home/circleci/project/semantic-release-remote/commit/eeba9f36fef825e1cbd02322db488cc75f467049)) - -# [2.1.0-develop.1](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.8...v2.1.0-develop.1) (2023-08-08) - - -### Features - -* **deps:** update dependency scratch-vm to v1.6.0 ([f85e72c](https:/home/circleci/project/semantic-release-remote/commit/f85e72c48afbe1f4ae95b83f8166b6b0afd06751)) - -## [2.0.3-develop.8](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.7...v2.0.3-develop.8) (2023-08-08) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.98 ([42d8912](https:/home/circleci/project/semantic-release-remote/commit/42d8912b824ed9c18f9a5585050df77d77057d8f)) - -## [2.0.3-develop.7](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.6...v2.0.3-develop.7) (2023-08-06) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.97 ([490155c](https:/home/circleci/project/semantic-release-remote/commit/490155c249ea5495081d16681540feec5471be88)) - -## [2.0.3-develop.6](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.5...v2.0.3-develop.6) (2023-08-05) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.96 ([9a46cbd](https:/home/circleci/project/semantic-release-remote/commit/9a46cbdd45d6f0955d070e5b1c2c75e343deef6a)) - -## [2.0.3-develop.5](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.4...v2.0.3-develop.5) (2023-08-04) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.95 ([71a0b81](https:/home/circleci/project/semantic-release-remote/commit/71a0b81b456b5b60a84011a76c209a1074776697)) - -## [2.0.3-develop.4](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.3...v2.0.3-develop.4) (2023-08-03) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.94 ([414055a](https:/home/circleci/project/semantic-release-remote/commit/414055a3cd3824379dde09c5a34a41658b372bc9)) - -## [2.0.3-develop.3](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.2...v2.0.3-develop.3) (2023-08-02) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.93 ([cd024c6](https:/home/circleci/project/semantic-release-remote/commit/cd024c6698914ef7ff8854f10753ff2ff13f2e8c)) - -## [2.0.3-develop.2](https:/home/circleci/project/semantic-release-remote/compare/v2.0.3-develop.1...v2.0.3-develop.2) (2023-08-01) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.92 ([26f1c6a](https:/home/circleci/project/semantic-release-remote/commit/26f1c6ae250ed240a5159a20a634264bfd98480b)) - -## [2.0.3-develop.1](https:/home/circleci/project/semantic-release-remote/compare/v2.0.2...v2.0.3-develop.1) (2023-07-27) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.43 ([b75b289](https:/home/circleci/project/semantic-release-remote/commit/b75b2896a580e76282344e8b5c6ee404de85adfa)) -* **deps:** update dependency scratch-vm to v1.5.91 ([524712f](https:/home/circleci/project/semantic-release-remote/commit/524712fa1716ac952f984511c18ab8d53f2155ae)) -* **win:** apply the calculated version number to packaging output ([57a6ebc](https:/home/circleci/project/semantic-release-remote/commit/57a6ebc1df4e7bf32e599e4b6a93b149f3f34053)) -* **WinBLE:** disconnect event handlers during session dispose ([3b15ac5](https:/home/circleci/project/semantic-release-remote/commit/3b15ac5e3988b6596eb1c3d6417dca89e68a38f8)) -* **Win:** fix sizing problem in context menu ([c35c934](https:/home/circleci/project/semantic-release-remote/commit/c35c93496a58349c0fd9b0341a23a94cb4107e36)) - -## [2.0.2-develop.4](https:/home/circleci/project/semantic-release-remote/compare/v2.0.2-develop.3...v2.0.2-develop.4) (2023-07-26) - - -### Bug Fixes - -* **win:** apply the calculated version number to packaging output ([57a6ebc](https:/home/circleci/project/semantic-release-remote/commit/57a6ebc1df4e7bf32e599e4b6a93b149f3f34053)) - -## [2.0.2-develop.3](https:/home/circleci/project/semantic-release-remote/compare/v2.0.2-develop.2...v2.0.2-develop.3) (2023-07-05) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.43 ([b75b289](https:/home/circleci/project/semantic-release-remote/commit/b75b2896a580e76282344e8b5c6ee404de85adfa)) - -## [2.0.2-develop.2](https:/home/circleci/project/semantic-release-remote/compare/v2.0.2-develop.1...v2.0.2-develop.2) (2023-06-09) - - -### Bug Fixes - -* **Win:** fix sizing problem in context menu ([c35c934](https:/home/circleci/project/semantic-release-remote/commit/c35c93496a58349c0fd9b0341a23a94cb4107e36)) - -## [2.0.2-develop.1](https:/home/circleci/project/semantic-release-remote/compare/v2.0.1...v2.0.2-develop.1) (2023-06-08) - - -### Bug Fixes - -* **WinBLE:** disconnect event handlers during session dispose ([3b15ac5](https:/home/circleci/project/semantic-release-remote/commit/3b15ac5e3988b6596eb1c3d6417dca89e68a38f8)) - -## [2.0.1](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0...v2.0.1) (2023-05-25) - - -### Bug Fixes - -* **mac:** even more versioning fixes ([07c035d](https:/home/circleci/project/semantic-release-remote/commit/07c035dea84a16ce02368cc1bb5f7f32ff1b3885)) - -# [2.0.0](https:/home/circleci/project/semantic-release-remote/compare/v1.4.0...v2.0.0) (2023-05-25) - - -### Bug Fixes - -* always call context.completeRequest, even when not returning a value ([9cabb03](https:/home/circleci/project/semantic-release-remote/commit/9cabb03495b089cdc23fb257a0c3fea7e603c225)) -* **build:** fix missing CFBundleVersion in Safari extension ([7a67ea1](https:/home/circleci/project/semantic-release-remote/commit/7a67ea18025396c26a359f435a2c1cb1ed7ab8c3)) -* calculate build number from label ([2eb8015](https:/home/circleci/project/semantic-release-remote/commit/2eb8015d457263111219f2fc4a5e7d5505c6efb4)) -* **ci:** speculative fix for Homebrew failing on CI ([4b12ce4](https:/home/circleci/project/semantic-release-remote/commit/4b12ce4d1501eaea92ee76c1e11fc808ccc7ad11)) -* **ci:** update VS Mac installer script for 17.4 ([9221e1e](https:/home/circleci/project/semantic-release-remote/commit/9221e1e68a0c5cb8e35777c914fd9e17e954a5d7)) -* **common:** make session immediately so we don't miss the first message ([d53d5c8](https:/home/circleci/project/semantic-release-remote/commit/d53d5c8a9dd02563c5e75208cfc7125386d5f85a)) -* **common:** remove `EventAwaiter(EventHandler, ...` ([9032a01](https:/home/circleci/project/semantic-release-remote/commit/9032a013c8b5dc967f5a53a50546499b55af6b55)) -* **deps:** update dependency scratch-vm to v1.5.28 ([441b7fd](https:/home/circleci/project/semantic-release-remote/commit/441b7fdf3572b093d3b4c0c1022e5472dbcdaff9)) -* **deps:** update dependency scratch-vm to v1.5.31 ([2c60027](https:/home/circleci/project/semantic-release-remote/commit/2c60027674e6cb3f0942d2c380b01b765bef12f8)) -* **deps:** update dependency scratch-vm to v1.5.32 ([964a53f](https:/home/circleci/project/semantic-release-remote/commit/964a53f0ed1e594d1cf3e983c9830402ce743f05)) -* **deps:** update dependency scratch-vm to v1.5.33 ([1c3a4cf](https:/home/circleci/project/semantic-release-remote/commit/1c3a4cfd0b13ca938cd53b44e26491415ea80e43)) -* **deps:** update dependency scratch-vm to v1.5.34 ([b19fe2a](https:/home/circleci/project/semantic-release-remote/commit/b19fe2a64639e4ff17cd965d82965bfea6ce0603)) -* **deps:** update dependency scratch-vm to v1.5.35 ([7543466](https:/home/circleci/project/semantic-release-remote/commit/7543466407de1f1f297afd148f07036bd977109b)) -* **deps:** update dependency scratch-vm to v1.5.36 ([cbc0e7c](https:/home/circleci/project/semantic-release-remote/commit/cbc0e7ca8f472199acc52a2e408a878e462d0240)) -* **deps:** update dependency scratch-vm to v1.5.37 ([79af6ab](https:/home/circleci/project/semantic-release-remote/commit/79af6ab191eb881c14e0403a5524c4da42e865d6)) -* **deps:** update dependency scratch-vm to v1.5.38 ([f200619](https:/home/circleci/project/semantic-release-remote/commit/f2006198489bc938ce4c46ec879fe4d182ec8c5f)) -* **deps:** update dependency scratch-vm to v1.5.40 ([f2b6787](https:/home/circleci/project/semantic-release-remote/commit/f2b67876984b75fca7286902be800d584959f58a)) -* **deps:** update dependency scratch-vm to v1.5.41 ([5e25dba](https:/home/circleci/project/semantic-release-remote/commit/5e25dba6cceb03df542aa1e4d920326f3f0b534e)) -* **deps:** update dependency scratch-vm to v1.5.42 ([7d8d1b2](https:/home/circleci/project/semantic-release-remote/commit/7d8d1b25a873866aef4cf9fe12a664ab94ada90d)) -* disable BLE restore to fix 'Bluetooth unavailable' issue ([8fdc3d1](https:/home/circleci/project/semantic-release-remote/commit/8fdc3d166edb6fb49b25ed2f467a0f77227dc630)) -* dispose of cbManager on session shutdown ([5423e78](https:/home/circleci/project/semantic-release-remote/commit/5423e7800ba21bdb50874d23a88d0cee64c2c54d)) -* don't embed IOBluetooth.framework ([563070d](https:/home/circleci/project/semantic-release-remote/commit/563070d67e5a88cc96a196759f2d2b59b0f4706b)) -* **extension:** inject project marketing version into web extension manifest ([6aa609d](https:/home/circleci/project/semantic-release-remote/commit/6aa609d100961b7f74f4345c28137393988a2835)) -* fix DisposedException by removing cancellation token ([eed937f](https:/home/circleci/project/semantic-release-remote/commit/eed937fd185f58295733e63dc8879a32e5a5ee10)) -* fix minor MAS compliance issues ([149076c](https:/home/circleci/project/semantic-release-remote/commit/149076c07aa6c6e725e09130ee23a397b3e6e9eb)) -* generate icons directly from SVGs for better quality ([8d3b8ce](https:/home/circleci/project/semantic-release-remote/commit/8d3b8ce38a1000552d92bdce7da1cf98fbd9b134)) -* implement a BT connection dance that works on macOS 10 and 12 ([159ca00](https:/home/circleci/project/semantic-release-remote/commit/159ca006789956de12e4282b2d088217eb5bb17a)) -* **Mac:** add real Bluetooth permissions request messages ([39cdf3c](https:/home/circleci/project/semantic-release-remote/commit/39cdf3cd509a1c475dbc80b08d919607a6ac1f22)) -* **Mac:** add real icons for Safari extension ([f081c71](https:/home/circleci/project/semantic-release-remote/commit/f081c7130d97a86f55259bd76eef4fdd51bd1856)) -* **MacBLE:** allow more time for the Bluetooth state to settle ([d2c1cf9](https:/home/circleci/project/semantic-release-remote/commit/d2c1cf97845060e88a00d69a66c13580abb7c74e)) -* **macBLE:** fix 'API MISUSE' log message ([b46f435](https:/home/circleci/project/semantic-release-remote/commit/b46f4359f6ed9feb8734cfbc66d9936af6303201)) -* **macBLE:** handle UpdatedState even if it fires during CBCentralManager ctor ([d2df409](https:/home/circleci/project/semantic-release-remote/commit/d2df40995861311b02875c03c2f2151038e3c8e5)) -* **macBT:** add 'Options' / PIN instructions to pairing dialog ([d58f5d2](https:/home/circleci/project/semantic-release-remote/commit/d58f5d243aeafb7756c987350b439b698c7eaa7d)) -* **MacBT:** dispose of inquiry & channel properly ([b3c48ef](https:/home/circleci/project/semantic-release-remote/commit/b3c48ef1662a93776e68181a5e745a4b88b9670d)) -* **MacBT:** make BT disconnect/reconnect more reliable, especially after pairing ([53bbe3b](https:/home/circleci/project/semantic-release-remote/commit/53bbe3b6e39fc9b27bf11119c888c4b36a39771c)) -* **macBT:** poll to reliably detect RFCOMM channel open ([d42cfdb](https:/home/circleci/project/semantic-release-remote/commit/d42cfdb63751ce511f2053ff4130e2a41b99a751)) -* **Mac:** correct target macOS version ([71e7a13](https:/home/circleci/project/semantic-release-remote/commit/71e7a1303397c7138604131c89bbdcf5793adc9a)) -* **Mac:** embed Safari helper extension into the Scratch Link app bundle ([9c6bb30](https:/home/circleci/project/semantic-release-remote/commit/9c6bb30273b4597e1e3ddd451167cffe6231a854)) -* **mac:** fix CI artifact renaming ([7a05fdd](https:/home/circleci/project/semantic-release-remote/commit/7a05fdda50fc7a498bbdc6d4068cf305177669b7)) -* **Mac:** fix Safari, especially Link->Client notifications ([5bae1ea](https:/home/circleci/project/semantic-release-remote/commit/5bae1ea319dd96eed6a92074a1ba59ecdaca89ca)) -* **mac:** fix tccd error message about kTCCServiceAppleEvents ([bdfc8c0](https:/home/circleci/project/semantic-release-remote/commit/bdfc8c08a6caae205e599b9cca28aedc627d1589)) -* **Mac:** hide Safari extensions for non-MAS builds ([58138c5](https:/home/circleci/project/semantic-release-remote/commit/58138c5c89d17ff6d4dfd40d1bfa3ad95c88f27b)) -* **Mac:** make sure GetSettledBluetoothState() doesn't miss an event ([124b6a0](https:/home/circleci/project/semantic-release-remote/commit/124b6a0cef58bd027249656ac4d183f76454d8f5)) -* **Mac:** properly Dispose() of the status bar item ([4cb46b5](https:/home/circleci/project/semantic-release-remote/commit/4cb46b56588d74cd8cf54e79f36a7a6fafe53f59)) -* **Mac:** remove browser_action popup ([9717935](https:/home/circleci/project/semantic-release-remote/commit/971793558fdf949622c79e28db93dd43083c8938)) -* **Mac:** Safari extension improvements ([14f9f99](https:/home/circleci/project/semantic-release-remote/commit/14f9f99b8cb25e7704e53f31f6589f7205b4c66a)) -* **Mac:** show Safari extension menu only if supported ([d019142](https:/home/circleci/project/semantic-release-remote/commit/d01914241789fc639def818f8553799b2915c198)) -* make CI robust against VS updates ([950d3de](https:/home/circleci/project/semantic-release-remote/commit/950d3deb307226403b537874cadb1f64d2886ac6)) -* make didDiscoverPeripheral a notification ([e51fa01](https:/home/circleci/project/semantic-release-remote/commit/e51fa01b799fcc2c9030a66c4bfe448f4aabbc08)) -* **menu:** 'Manage Safari Extensions' => 'Manage Safari Extensions...' ([dc5c481](https:/home/circleci/project/semantic-release-remote/commit/dc5c48127842be5e3f756f077a0d1e284d1002e8)) -* more BT connection tweaks ([7a1e0d0](https:/home/circleci/project/semantic-release-remote/commit/7a1e0d014a05f3af968d998c2caf888987501618)) -* resolve crash on session close while connecting ([32f8981](https:/home/circleci/project/semantic-release-remote/commit/32f89814873eb19045cffcfe40a3c96f70bce54b)) -* **Safari:** add timeout for initial connection ([e1c9de0](https:/home/circleci/project/semantic-release-remote/commit/e1c9de00f1dbf55c1da8bd2bd935f23015b34450)) -* **Safari:** close session if Scratch Link goes away ([83f85f0](https:/home/circleci/project/semantic-release-remote/commit/83f85f028996d12e2a7d6f2b6c4f93608d60bef8)) -* **safari:** don't cause Safari to steal focus for every Scratch Link -> page message ([f17184f](https:/home/circleci/project/semantic-release-remote/commit/f17184f5a1e163232a0ee76133cd2953bb382a0d)) -* use semantic-release version for build ([17709dd](https:/home/circleci/project/semantic-release-remote/commit/17709dd709a59a1b4d5fa10b4a4ed50834ffd893)) -* **version:** embed GitVersion info correctly and document version scheme ([6501e49](https:/home/circleci/project/semantic-release-remote/commit/6501e49073ac852e71ccd048973fb7b5a383c506)) -* **webextension:** close session on client unload ([caac99e](https:/home/circleci/project/semantic-release-remote/commit/caac99e9c0fa15a940642dc5c9063dba45a40b5f)) -* **webextension:** keep Safari sessions alive for longer than 5 seconds ([4981508](https:/home/circleci/project/semantic-release-remote/commit/498150869982c3d21f5463cf646e337fd789b970)) -* **webextension:** limit number of outstanding poll requests ([c5137bb](https:/home/circleci/project/semantic-release-remote/commit/c5137bb7a06c1701592669196508ae9b26ee97be)) -* **win:** build framework-dependent AnyCPU for further install size reduction ([b1f776c](https:/home/circleci/project/semantic-release-remote/commit/b1f776c19f07652ea09c3152325a35578f9fdcf1)) -* **win:** discover both paired and unpaired BT devices ([23ff634](https:/home/circleci/project/semantic-release-remote/commit/23ff634560930041ebb66ae6476839825bb713ba)) -* **win:** don't crash if BT connect fails ([522f65f](https:/home/circleci/project/semantic-release-remote/commit/522f65f199741e2e704f716952a2db8c7508640f)) -* **windows:** fix *.msixupload generation ([3a1c172](https:/home/circleci/project/semantic-release-remote/commit/3a1c1727bcfbe46aa549a4c15b3b0f7e750b0527)) -* **windows:** fix incorrect root namespace ([e25a604](https:/home/circleci/project/semantic-release-remote/commit/e25a604be0238ef3501447df411c7816aea31f26)) -* **windows:** implement WinBLESession.Dispose ([9a0e1f7](https:/home/circleci/project/semantic-release-remote/commit/9a0e1f7ec1202ae24abc5ca988c4fa54c822bffd)) -* **Win:** fix larger icon sizes being ignored sometimes ([e79252f](https:/home/circleci/project/semantic-release-remote/commit/e79252f2ddf2e15987aab8e2205a95aceaa80cb1)) -* **Win:** set assembly attributes including version info ([8379c15](https:/home/circleci/project/semantic-release-remote/commit/8379c153d9b4273bf0e2814a3ebf6be3f2d3e260)) -* **win:** set WindowsPackageType=None to fix debugging ([4b151e1](https:/home/circleci/project/semantic-release-remote/commit/4b151e1884915a39f059d696a968557f04e4ff7b)) -* work around macOS 12 OpenRfcommChannelSync timeout ([68e7efc](https:/home/circleci/project/semantic-release-remote/commit/68e7efc069e8188dd7ee4d0b0e5deff43d7bdd14)) - - -### chore - -* clean slate for Scratch Link 2.0 ([f30cff3](https:/home/circleci/project/semantic-release-remote/commit/f30cff3e5b0fbd2fda423e8609cbd6576c45131a)) - - -### Features - -* add Windows tray icon ([29b961b](https:/home/circleci/project/semantic-release-remote/commit/29b961b8bb86070fb67012def05f195b75438086)) -* **MacBT:** display pairing help when connecting to unpaired peripheral ([feb100e](https:/home/circleci/project/semantic-release-remote/commit/feb100e3c0e40ce34759246ca27b247ecbb201fc)) -* **Safari:** inject client script into page if script ID is present ([9bc1ef4](https:/home/circleci/project/semantic-release-remote/commit/9bc1ef433ced60b1dc40dc68d0ffe833ce137199)) -* **Win:** add proper Windows icon for app and tray ([e0e96c2](https:/home/circleci/project/semantic-release-remote/commit/e0e96c23e791eef77e136f4188a0fa621c1f0cb3)) -* **win:** convert BT session for Scratch Link 2.0 ([b2bc874](https:/home/circleci/project/semantic-release-remote/commit/b2bc874b7dea108b10fe2eaa4cd8cdd42a1b4f76)) -* **windows:** BLE session first draft ([224e694](https:/home/circleci/project/semantic-release-remote/commit/224e6948749997395102f2c2de2e12163627c37a)) -* **windows:** build and run ScratchApp, receive WS connections ([05d2866](https:/home/circleci/project/semantic-release-remote/commit/05d2866f2bca7f3bee8af67e0769458b7c4399e9)) -* **windows:** generate image assets for MSIX ([d77a006](https:/home/circleci/project/semantic-release-remote/commit/d77a0064a0cd25bac8b8b2b7e3c7d0b146ead69a)) - - -### Performance Improvements - -* **Win:** shrink tray icon, speed up svg-convert.sh ([adeaf1d](https:/home/circleci/project/semantic-release-remote/commit/adeaf1da6b1f48ce993391aa764a0acf53898f74)) - - -### BREAKING CHANGES - -* Scratch Link 2.0 will drop support for some older -versions of macOS. - -# [2.0.0-develop.18](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.17...v2.0.0-develop.18) (2023-05-24) - - -### Bug Fixes - -* **build:** fix missing CFBundleVersion in Safari extension ([7a67ea1](https:/home/circleci/project/semantic-release-remote/commit/7a67ea18025396c26a359f435a2c1cb1ed7ab8c3)) - -# [2.0.0-develop.17](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.16...v2.0.0-develop.17) (2023-04-29) - - -### Bug Fixes - -* **Win:** fix larger icon sizes being ignored sometimes ([e79252f](https:/home/circleci/project/semantic-release-remote/commit/e79252f2ddf2e15987aab8e2205a95aceaa80cb1)) -* **Win:** set assembly attributes including version info ([8379c15](https:/home/circleci/project/semantic-release-remote/commit/8379c153d9b4273bf0e2814a3ebf6be3f2d3e260)) - - -### Features - -* add Windows tray icon ([29b961b](https:/home/circleci/project/semantic-release-remote/commit/29b961b8bb86070fb67012def05f195b75438086)) -* **Win:** add proper Windows icon for app and tray ([e0e96c2](https:/home/circleci/project/semantic-release-remote/commit/e0e96c23e791eef77e136f4188a0fa621c1f0cb3)) - - -### Performance Improvements - -* **Win:** shrink tray icon, speed up svg-convert.sh ([adeaf1d](https:/home/circleci/project/semantic-release-remote/commit/adeaf1da6b1f48ce993391aa764a0acf53898f74)) - -# [2.0.0-develop.16](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.15...v2.0.0-develop.16) (2023-04-24) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.42 ([7d8d1b2](https:/home/circleci/project/semantic-release-remote/commit/7d8d1b25a873866aef4cf9fe12a664ab94ada90d)) - -# [2.0.0-develop.15](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.14...v2.0.0-develop.15) (2023-04-22) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.41 ([5e25dba](https:/home/circleci/project/semantic-release-remote/commit/5e25dba6cceb03df542aa1e4d920326f3f0b534e)) - -# [2.0.0-develop.14](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.13...v2.0.0-develop.14) (2023-04-22) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.40 ([f2b6787](https:/home/circleci/project/semantic-release-remote/commit/f2b67876984b75fca7286902be800d584959f58a)) - -# [2.0.0-develop.13](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.12...v2.0.0-develop.13) (2023-04-21) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.38 ([f200619](https:/home/circleci/project/semantic-release-remote/commit/f2006198489bc938ce4c46ec879fe4d182ec8c5f)) - -# [2.0.0-develop.12](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.11...v2.0.0-develop.12) (2023-04-21) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.37 ([79af6ab](https:/home/circleci/project/semantic-release-remote/commit/79af6ab191eb881c14e0403a5524c4da42e865d6)) - -# [2.0.0-develop.11](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.10...v2.0.0-develop.11) (2023-04-20) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.36 ([cbc0e7c](https:/home/circleci/project/semantic-release-remote/commit/cbc0e7ca8f472199acc52a2e408a878e462d0240)) - -# [2.0.0-develop.10](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.9...v2.0.0-develop.10) (2023-04-19) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.35 ([7543466](https:/home/circleci/project/semantic-release-remote/commit/7543466407de1f1f297afd148f07036bd977109b)) - -# [2.0.0-develop.9](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.8...v2.0.0-develop.9) (2023-04-19) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.34 ([b19fe2a](https:/home/circleci/project/semantic-release-remote/commit/b19fe2a64639e4ff17cd965d82965bfea6ce0603)) - -# [2.0.0-develop.8](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.7...v2.0.0-develop.8) (2023-04-17) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.33 ([1c3a4cf](https:/home/circleci/project/semantic-release-remote/commit/1c3a4cfd0b13ca938cd53b44e26491415ea80e43)) - -# [2.0.0-develop.7](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.6...v2.0.0-develop.7) (2023-04-15) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.32 ([964a53f](https:/home/circleci/project/semantic-release-remote/commit/964a53f0ed1e594d1cf3e983c9830402ce743f05)) - -# [2.0.0-develop.6](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.5...v2.0.0-develop.6) (2023-04-14) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.31 ([2c60027](https:/home/circleci/project/semantic-release-remote/commit/2c60027674e6cb3f0942d2c380b01b765bef12f8)) - -# [2.0.0-develop.5](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.4...v2.0.0-develop.5) (2023-04-06) - - -### Bug Fixes - -* generate icons directly from SVGs for better quality ([8d3b8ce](https:/home/circleci/project/semantic-release-remote/commit/8d3b8ce38a1000552d92bdce7da1cf98fbd9b134)) -* **mac:** fix CI artifact renaming ([7a05fdd](https:/home/circleci/project/semantic-release-remote/commit/7a05fdda50fc7a498bbdc6d4068cf305177669b7)) -* **win:** build framework-dependent AnyCPU for further install size reduction ([b1f776c](https:/home/circleci/project/semantic-release-remote/commit/b1f776c19f07652ea09c3152325a35578f9fdcf1)) -* **win:** discover both paired and unpaired BT devices ([23ff634](https:/home/circleci/project/semantic-release-remote/commit/23ff634560930041ebb66ae6476839825bb713ba)) -* **win:** don't crash if BT connect fails ([522f65f](https:/home/circleci/project/semantic-release-remote/commit/522f65f199741e2e704f716952a2db8c7508640f)) -* **windows:** fix *.msixupload generation ([3a1c172](https:/home/circleci/project/semantic-release-remote/commit/3a1c1727bcfbe46aa549a4c15b3b0f7e750b0527)) -* **windows:** fix incorrect root namespace ([e25a604](https:/home/circleci/project/semantic-release-remote/commit/e25a604be0238ef3501447df411c7816aea31f26)) -* **windows:** implement WinBLESession.Dispose ([9a0e1f7](https:/home/circleci/project/semantic-release-remote/commit/9a0e1f7ec1202ae24abc5ca988c4fa54c822bffd)) -* **win:** set WindowsPackageType=None to fix debugging ([4b151e1](https:/home/circleci/project/semantic-release-remote/commit/4b151e1884915a39f059d696a968557f04e4ff7b)) - - -### Features - -* **win:** convert BT session for Scratch Link 2.0 ([b2bc874](https:/home/circleci/project/semantic-release-remote/commit/b2bc874b7dea108b10fe2eaa4cd8cdd42a1b4f76)) -* **windows:** BLE session first draft ([224e694](https:/home/circleci/project/semantic-release-remote/commit/224e6948749997395102f2c2de2e12163627c37a)) -* **windows:** build and run ScratchApp, receive WS connections ([05d2866](https:/home/circleci/project/semantic-release-remote/commit/05d2866f2bca7f3bee8af67e0769458b7c4399e9)) -* **windows:** generate image assets for MSIX ([d77a006](https:/home/circleci/project/semantic-release-remote/commit/d77a0064a0cd25bac8b8b2b7e3c7d0b146ead69a)) - -# [2.0.0-develop.4](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.3...v2.0.0-develop.4) (2023-04-06) - - -### Bug Fixes - -* calculate build number from label ([2eb8015](https:/home/circleci/project/semantic-release-remote/commit/2eb8015d457263111219f2fc4a5e7d5505c6efb4)) - -# [2.0.0-develop.3](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.2...v2.0.0-develop.3) (2023-04-06) - - -### Bug Fixes - -* **deps:** update dependency scratch-vm to v1.5.28 ([441b7fd](https:/home/circleci/project/semantic-release-remote/commit/441b7fdf3572b093d3b4c0c1022e5472dbcdaff9)) - -# [2.0.0-develop.2](https:/home/circleci/project/semantic-release-remote/compare/v2.0.0-develop.1...v2.0.0-develop.2) (2023-04-06) - - -### Bug Fixes - -* use semantic-release version for build ([17709dd](https:/home/circleci/project/semantic-release-remote/commit/17709dd709a59a1b4d5fa10b4a4ed50834ffd893)) - -# [2.0.0-develop.1](https:/home/circleci/project/semantic-release-remote/compare/v1.4.0...v2.0.0-develop.1) (2023-04-06) - - -### Bug Fixes - -* always call context.completeRequest, even when not returning a value ([9cabb03](https:/home/circleci/project/semantic-release-remote/commit/9cabb03495b089cdc23fb257a0c3fea7e603c225)) -* **ci:** speculative fix for Homebrew failing on CI ([4b12ce4](https:/home/circleci/project/semantic-release-remote/commit/4b12ce4d1501eaea92ee76c1e11fc808ccc7ad11)) -* **ci:** update VS Mac installer script for 17.4 ([9221e1e](https:/home/circleci/project/semantic-release-remote/commit/9221e1e68a0c5cb8e35777c914fd9e17e954a5d7)) -* **common:** make session immediately so we don't miss the first message ([d53d5c8](https:/home/circleci/project/semantic-release-remote/commit/d53d5c8a9dd02563c5e75208cfc7125386d5f85a)) -* **common:** remove `EventAwaiter(EventHandler, ...` ([9032a01](https:/home/circleci/project/semantic-release-remote/commit/9032a013c8b5dc967f5a53a50546499b55af6b55)) -* disable BLE restore to fix 'Bluetooth unavailable' issue ([8fdc3d1](https:/home/circleci/project/semantic-release-remote/commit/8fdc3d166edb6fb49b25ed2f467a0f77227dc630)) -* dispose of cbManager on session shutdown ([5423e78](https:/home/circleci/project/semantic-release-remote/commit/5423e7800ba21bdb50874d23a88d0cee64c2c54d)) -* don't embed IOBluetooth.framework ([563070d](https:/home/circleci/project/semantic-release-remote/commit/563070d67e5a88cc96a196759f2d2b59b0f4706b)) -* **extension:** inject project marketing version into web extension manifest ([6aa609d](https:/home/circleci/project/semantic-release-remote/commit/6aa609d100961b7f74f4345c28137393988a2835)) -* fix DisposedException by removing cancellation token ([eed937f](https:/home/circleci/project/semantic-release-remote/commit/eed937fd185f58295733e63dc8879a32e5a5ee10)) -* fix minor MAS compliance issues ([149076c](https:/home/circleci/project/semantic-release-remote/commit/149076c07aa6c6e725e09130ee23a397b3e6e9eb)) -* implement a BT connection dance that works on macOS 10 and 12 ([159ca00](https:/home/circleci/project/semantic-release-remote/commit/159ca006789956de12e4282b2d088217eb5bb17a)) -* **Mac:** add real Bluetooth permissions request messages ([39cdf3c](https:/home/circleci/project/semantic-release-remote/commit/39cdf3cd509a1c475dbc80b08d919607a6ac1f22)) -* **Mac:** add real icons for Safari extension ([f081c71](https:/home/circleci/project/semantic-release-remote/commit/f081c7130d97a86f55259bd76eef4fdd51bd1856)) -* **MacBLE:** allow more time for the Bluetooth state to settle ([d2c1cf9](https:/home/circleci/project/semantic-release-remote/commit/d2c1cf97845060e88a00d69a66c13580abb7c74e)) -* **macBLE:** fix 'API MISUSE' log message ([b46f435](https:/home/circleci/project/semantic-release-remote/commit/b46f4359f6ed9feb8734cfbc66d9936af6303201)) -* **macBLE:** handle UpdatedState even if it fires during CBCentralManager ctor ([d2df409](https:/home/circleci/project/semantic-release-remote/commit/d2df40995861311b02875c03c2f2151038e3c8e5)) -* **macBT:** add 'Options' / PIN instructions to pairing dialog ([d58f5d2](https:/home/circleci/project/semantic-release-remote/commit/d58f5d243aeafb7756c987350b439b698c7eaa7d)) -* **MacBT:** dispose of inquiry & channel properly ([b3c48ef](https:/home/circleci/project/semantic-release-remote/commit/b3c48ef1662a93776e68181a5e745a4b88b9670d)) -* **MacBT:** make BT disconnect/reconnect more reliable, especially after pairing ([53bbe3b](https:/home/circleci/project/semantic-release-remote/commit/53bbe3b6e39fc9b27bf11119c888c4b36a39771c)) -* **macBT:** poll to reliably detect RFCOMM channel open ([d42cfdb](https:/home/circleci/project/semantic-release-remote/commit/d42cfdb63751ce511f2053ff4130e2a41b99a751)) -* **Mac:** correct target macOS version ([71e7a13](https:/home/circleci/project/semantic-release-remote/commit/71e7a1303397c7138604131c89bbdcf5793adc9a)) -* **Mac:** embed Safari helper extension into the Scratch Link app bundle ([9c6bb30](https:/home/circleci/project/semantic-release-remote/commit/9c6bb30273b4597e1e3ddd451167cffe6231a854)) -* **Mac:** fix Safari, especially Link->Client notifications ([5bae1ea](https:/home/circleci/project/semantic-release-remote/commit/5bae1ea319dd96eed6a92074a1ba59ecdaca89ca)) -* **mac:** fix tccd error message about kTCCServiceAppleEvents ([bdfc8c0](https:/home/circleci/project/semantic-release-remote/commit/bdfc8c08a6caae205e599b9cca28aedc627d1589)) -* **Mac:** hide Safari extensions for non-MAS builds ([58138c5](https:/home/circleci/project/semantic-release-remote/commit/58138c5c89d17ff6d4dfd40d1bfa3ad95c88f27b)) -* **Mac:** make sure GetSettledBluetoothState() doesn't miss an event ([124b6a0](https:/home/circleci/project/semantic-release-remote/commit/124b6a0cef58bd027249656ac4d183f76454d8f5)) -* **Mac:** properly Dispose() of the status bar item ([4cb46b5](https:/home/circleci/project/semantic-release-remote/commit/4cb46b56588d74cd8cf54e79f36a7a6fafe53f59)) -* **Mac:** remove browser_action popup ([9717935](https:/home/circleci/project/semantic-release-remote/commit/971793558fdf949622c79e28db93dd43083c8938)) -* **Mac:** Safari extension improvements ([14f9f99](https:/home/circleci/project/semantic-release-remote/commit/14f9f99b8cb25e7704e53f31f6589f7205b4c66a)) -* **Mac:** show Safari extension menu only if supported ([d019142](https:/home/circleci/project/semantic-release-remote/commit/d01914241789fc639def818f8553799b2915c198)) -* make CI robust against VS updates ([950d3de](https:/home/circleci/project/semantic-release-remote/commit/950d3deb307226403b537874cadb1f64d2886ac6)) -* make didDiscoverPeripheral a notification ([e51fa01](https:/home/circleci/project/semantic-release-remote/commit/e51fa01b799fcc2c9030a66c4bfe448f4aabbc08)) -* **menu:** 'Manage Safari Extensions' => 'Manage Safari Extensions...' ([dc5c481](https:/home/circleci/project/semantic-release-remote/commit/dc5c48127842be5e3f756f077a0d1e284d1002e8)) -* more BT connection tweaks ([7a1e0d0](https:/home/circleci/project/semantic-release-remote/commit/7a1e0d014a05f3af968d998c2caf888987501618)) -* resolve crash on session close while connecting ([32f8981](https:/home/circleci/project/semantic-release-remote/commit/32f89814873eb19045cffcfe40a3c96f70bce54b)) -* **Safari:** add timeout for initial connection ([e1c9de0](https:/home/circleci/project/semantic-release-remote/commit/e1c9de00f1dbf55c1da8bd2bd935f23015b34450)) -* **Safari:** close session if Scratch Link goes away ([83f85f0](https:/home/circleci/project/semantic-release-remote/commit/83f85f028996d12e2a7d6f2b6c4f93608d60bef8)) -* **safari:** don't cause Safari to steal focus for every Scratch Link -> page message ([f17184f](https:/home/circleci/project/semantic-release-remote/commit/f17184f5a1e163232a0ee76133cd2953bb382a0d)) -* **version:** embed GitVersion info correctly and document version scheme ([6501e49](https:/home/circleci/project/semantic-release-remote/commit/6501e49073ac852e71ccd048973fb7b5a383c506)) -* **webextension:** close session on client unload ([caac99e](https:/home/circleci/project/semantic-release-remote/commit/caac99e9c0fa15a940642dc5c9063dba45a40b5f)) -* **webextension:** keep Safari sessions alive for longer than 5 seconds ([4981508](https:/home/circleci/project/semantic-release-remote/commit/498150869982c3d21f5463cf646e337fd789b970)) -* **webextension:** limit number of outstanding poll requests ([c5137bb](https:/home/circleci/project/semantic-release-remote/commit/c5137bb7a06c1701592669196508ae9b26ee97be)) -* work around macOS 12 OpenRfcommChannelSync timeout ([68e7efc](https:/home/circleci/project/semantic-release-remote/commit/68e7efc069e8188dd7ee4d0b0e5deff43d7bdd14)) - - -### chore - -* clean slate for Scratch Link 2.0 ([f30cff3](https:/home/circleci/project/semantic-release-remote/commit/f30cff3e5b0fbd2fda423e8609cbd6576c45131a)) - - -### Features - -* **MacBT:** display pairing help when connecting to unpaired peripheral ([feb100e](https:/home/circleci/project/semantic-release-remote/commit/feb100e3c0e40ce34759246ca27b247ecbb201fc)) -* **Safari:** inject client script into page if script ID is present ([9bc1ef4](https:/home/circleci/project/semantic-release-remote/commit/9bc1ef433ced60b1dc40dc68d0ffe833ce137199)) - - -### BREAKING CHANGES - -* Scratch Link 2.0 will drop support for some older -versions of macOS. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..9b730ffa --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,97 @@ +# AluxLabs Link — Claude 행동 규칙 + +Windows-only desktop app. Scratch 3.0 ↔ 하드웨어(BLE, Bluetooth Classic, USB Serial) 중계. +C# / .NET 8 + WinUI 3, Visual Studio Solution. + +--- + +## 1. 최우선 규칙 (위반 시 즉시 수정) + +- **`Console.*` 사용 금지** → `Trace.WriteLine()` (`System.Diagnostics`) 사용 (§4 참조) +- **`aluxlabs-link-common`이 `aluxlabs-link-win`을 참조 금지** → 의존 방향은 `aluxlabs-link-win → aluxlabs-link-common` 단방향 (§8 참조) +- **`SharedProps/*.props` / `*.targets` 직접 편집 시 주의** → 전체 빌드에 영향. 개별 csproj에서 중복 선언 금지 +- **기존 아키텍처·패턴을 우회하는 수정 금지** (§8 참조) → 새 코드·수정 코드에 적용. 기존 위반은 명시 요청 없이 건드리지 않는다. 단, 수정 범위 안에서 우회 코드를 발견하면 사용자에게 알리고 처리 여부를 묻는다. + +## 2. Using 지시문 규칙 + +- `using` 선언은 반드시 **namespace 내부**에 배치 (`.editorconfig` 강제) +- 멤버 접근 시 `this.` 한정자 필수: 필드(`this.field`), 메서드(`this.Method()`), 프로퍼티(`this.Property`), 이벤트(`this.Event`) +- 불필요한 `using` 추가 금지 — 미사용 using은 컴파일 경고 원인 + +## 3. 코드 스타일 + +- 인덴트: 4 스페이스 (탭 금지) +- 줄 끝: LF (XML / CSPROJ / WAPPROJ 제외 — CRLF) +- 인코딩: UTF-8 +- StyleCop Analyzers 준수 필수 +- `interface` 명명: `I` 접두사 (예: `ISession`, `IPeripheralSession`) +- 미사용 변수·using 금지 (`CS8600`, `IDE0005` 등 경고 발생) + +## 4. 금지 패턴 + +- **`Console.*` 사용 금지** → `Trace.WriteLine()` 사용 + - **예외 — 임시 진단용**: `System.Diagnostics.Debug.WriteLine("[DEBUG-XXX] ...")` 형태로 한정 허용. `[DEBUG-XXX]` 식별 prefix 필수 (grep 가능). **커밋 전 반드시 전부 제거**. +- **`dynamic` 타입 남용 금지** → 구체적 타입 또는 제네릭 사용 +- **`#pragma warning disable` 무분별 사용 금지** → 근본 원인 해결 우선 +- **`types.cs` / `type.cs` 파일 생성 금지** → 타입·인터페이스는 사용하는 클래스 파일 안에 함께 정의 (코로케이션) +- **일반 주석(`//`)은 한 줄 max, "WHY"만** → 기본은 주석 없음. WHY가 비자명할 때만 한 줄 추가. WHAT 설명 / 현재 작업·callers 참조 금지. 설계 의도는 commit message / PR description으로. +- **XML doc(`///`)은 public API에 한해 단일 `` 허용** → 단, caller 참조(`"Used by X"`) 및 코드에서 자명한 WHAT 설명 금지. 비자명한 동작·제약·사이드이펙트만 기술한다. +- **공용 코드 (`aluxlabs-link-common`) 의 주석·식별자에서 특정 프로토콜 구현 세부 언급 금지** → 일반화된 패턴 설명으로 표현하고, 구체적 예시는 해당 세션 클래스 안에서만 든다. + +## 5. 작업 전 확인사항 + +코드 작성·수정 전에 반드시 확인: + +1. 수정 대상 파일을 먼저 읽고 기존 패턴을 파악한다 +2. **`aluxlabs-link-common` vs `aluxlabs-link-win` 중 어느 쪽에 위치해야 하는지 판단한다** — 플랫폼 API(Windows.Devices.*, WinUI) 없이 동작 가능하면 common, 그렇지 않으면 win +3. 관련 타입·인터페이스가 이미 있는지 확인한다 +4. `SharedProps/`에 이미 선언된 속성·패키지 참조인지 확인한다 + +## 6. 작업 후 검증 체크리스트 + +- [ ] `Console.*`를 사용하지 않았는가? (임시 `[DEBUG-*]` 로그 전부 제거 확인) +- [ ] StyleCop 오류가 없는가? +- [ ] `using` 선언이 namespace 내부에 있는가? +- [ ] 멤버 접근에 `this.` 한정자를 사용했는가? +- [ ] 미사용 변수·using이 없는가? +- [ ] 의존 방향 규칙을 지켰는가? (`aluxlabs-link-common`이 `aluxlabs-link-win`을 참조하지 않음) +- [ ] `SharedProps/`에 이미 선언된 속성을 개별 csproj에 중복 선언하지 않았는가? +- [ ] 일반 주석(`//`)이 WHY만 담고 있는가? (WHAT / caller 참조 없음) +- [ ] XML doc(`///`)이 있다면 public API이고, caller 참조 및 자명한 WHAT 설명이 없는가? +- [ ] 기존 코드 패턴과 일관성이 있는가? + +## 7. 커밋 규칙 + +``` +feat(serial): USB Serial 트랜스포트 세션 추가 +fix(ble): BLE 연결 재시도 로직 오류 수정 +refactor(common): JSON-RPC 핸들러 구조 개선 +docs(architecture): Serial 프로토콜 설계 문서 업데이트 +``` + +- 접두사: `feat`, `fix`, `refactor`, `docs`, `chore`, `style`, `test`, `ci` +- scope 예시: `ble`, `bt`, `serial`, `common`, `win`, `jsonrpc`, `msix` +- 설명·본문·꼬리말은 한국어 + +## 8. 프로젝트 구조 핵심 + +- `aluxlabs-link-common/` — 플랫폼 공통 C# Shared Project (BLE/BT/Serial 프로토콜 추상화, JSON-RPC 2.0, WebSocket 핸들링). **재사용 가능한 단위로 분리**, Windows API에 종속되지 않는다. +- `aluxlabs-link-win/` — WinUI 3 플랫폼 구현 (Windows.Devices.* API 연동, 트레이 아이콘, 앱 진입점). **비즈니스 로직은 최소화**, 가능한 한 `aluxlabs-link-common`으로 위임. +- `aluxlabs-link-win-msix/` — MSIX 패키징 프로젝트. 앱·비즈니스 로직을 넣지 않는다. 단, 패키징·서명·self-contained·매니페스트 등 배포 구성 변경은 필요 시 여기서 수정하되, 배포 전반에 영향을 주므로 변경 후 빌드된 패키지를 검증한다. +- `SharedProps/` — MSBuild 공유 속성 (SDK 버전, NuGet 패키지 참조, 버전 자동화). 개별 csproj에서 중복 선언 금지. +- `Documentation/` — 아키텍처·프로토콜 설계 문서. 관련 코드 변경 시 함께 업데이트한다. +- **의존 방향: `aluxlabs-link-win` → `aluxlabs-link-common` 단방향** (§1 절대 규칙). 이유: common이 win을 참조하면 플랫폼 독립성이 깨지고 순환 의존이 발생한다. + +## 9. 개발 명령어 + +```bash +# 권장: Visual Studio 2022+에서 aluxlabs-link.sln 열기 +# 빌드 구성: Debug_Win / Release_Win + +dotnet build -c Debug_Win # 디버그 빌드 +dotnet build -c Release_Win # 릴리즈 빌드 +dotnet run --project aluxlabs-link-win -c Debug_Win # 실행 + +# 아이콘 생성 (cairosvg, ImageMagick, optipng 필요) +make icons +``` diff --git a/Documentation/Alux/CodeSigningAndDistribution.md b/Documentation/Alux/CodeSigningAndDistribution.md new file mode 100644 index 00000000..de62cd0a --- /dev/null +++ b/Documentation/Alux/CodeSigningAndDistribution.md @@ -0,0 +1,180 @@ +# 코드 서명 및 MSIX 배포 / 자동 업데이트 + +AluxLabs Link(`aluxlabs-link-win-msix`)를 코드 서명하고, sideload MSIX로 배포·자동 업데이트하는 절차. + +> ⚠️ 토큰 비밀번호·어드민 비밀번호 등 **비밀 값은 이 문서에 적지 않는다.** 별도의 비밀 보관처(비밀번호 관리자)에 둔다. + +## 0. 인증서 개요 + +- 종류: **Sectigo OV Code Signing** (Organization Validation) +- 형태: **하드웨어 토큰(eToken)** — 물리 USB 토큰 + `SafeNet Authentication Client` 필요 +- 인증서 Subject (= 매니페스트 Publisher와 일치시킬 값): **`CN="ALUX Co.,Ltd", O="ALUX Co.,Ltd", S=Seoul, C=KR`** +- 발급자: `Sectigo Public Code Signing CA R36` / 만료: **2027-07-01** (갱신 필요 시점) +- 지문(SHA1): `EB74741683C9CDCE4457571A7EDD075A835B02C6` — `signtool /sha1`에 사용 +- 동작 제약: + - 서명하려면 **토큰을 PC에 꽂고 SafeNet 클라이언트 + 토큰 비밀번호**가 있어야 한다. + - **토큰 비밀번호 3회 실패 시 잠김** → Sectigo 지원팀으로만 해제. 비밀번호 창은 복사·붙여넣기 가능(오타 방지 권장). + - SafeNet Authentication Client 다운로드: + - SafeNet 설치는 **Typical**(Microsoft Crypto Providers 포함) 선택 → `signtool`이 토큰 키에 접근 가능해진다. + +### OV의 한계 (알고 시작할 것) + +- **SmartScreen 평판은 즉시 생기지 않는다.** EV와 달리 다운로드·설치가 누적되어야 "알 수 없는 게시자" 경고가 사라진다. 초기 사용자는 경고를 볼 수 있다. +- **하드웨어 토큰이라 CI 자동 서명이 어렵다.** 토큰을 꽂은 머신에서만 서명되므로 **로컬 수동 서명**으로 운영한다. + +### 배포 트랙 (한 버킷, 파일명으로 분리) + +서명 주체가 둘이지만 **버킷은 `scratch-link`(prod)/`dev-scratch-link`(dev)로 공통**이다. 파일명이 달라 충돌하지 않는다. + +| 트랙 | 서명 | 파일 | 주체 | +|---|---|---|---| +| **실제 배포** | **USB 토큰(Sectigo)** | `AluxLabsLink.appinstaller` + `AluxLabs-Link-<버전>.msixbundle` | **수동** (이 문서) | +| CI/CD 테스트 | SignPath(신청 중) / 임시 인증서 | `latest.msixbundle` + `latest.json` + `archive/` | GitHub Actions (`release.yml`) | + +- 두 트랙은 **인증서 Subject가 달라 Publisher도 다르다** → 서로 자동 업데이트 안 됨(의도된 분리). +- CI 버킷은 `scripts/aws/setup-cdn.sh`가 만든 것. **CI 파일(`latest.*`, `archive/`)은 건드리지 않는다.** +- (`scratch-assets` 버킷도 검토했으나 공개 DNS가 없어 제외. `scratch-link`만 CloudFront로 공개 서빙됨.) + +## 1. 서명 도구 — SignTool + +표준 도구는 **`signtool.exe`** (Windows SDK 포함). + +- 위치: `C:\Program Files (x86)\Windows Kits\10\bin\<버전>\x64\signtool.exe` +- PATH에 없으므로 **Visual Studio의 "Developer PowerShell" / "Developer Command Prompt"** 에서 실행하면 자동으로 잡힌다. + +서명: + +```powershell +signtool sign /fd SHA256 /a /n "ALUX Co.,Ltd" ` + /tr http://timestamp.sectigo.com /td SHA256 ` + AluxLabsLink.msixbundle +``` + +- `/a` — 적합한 인증서 자동 선택 (토큰 인증서) +- `/n "ALUX Co.,Ltd"` — Subject 이름으로 인증서 지정 +- `/tr` + `/td SHA256` — 타임스탬프. **필수** (인증서 만료 후에도 서명 유효 유지) +- `/fd SHA256` — 파일 다이제스트 알고리즘 +- 실행 시 **SafeNet 비밀번호 창**이 팝업된다. (검증됨: 일반 PE 파일 시험 서명 성공 — 체인·타임스탬프 정상) + +확인: + +```powershell +signtool verify /pa /v AluxLabsLink.msixbundle +``` + +## 2. ⚠️ Publisher 일치 규칙 (MSIX 최대 함정) + +MSIX는 **서명 인증서의 Subject DN과 매니페스트 `Publisher`가 문자 그대로 정확히 일치**해야 한다. 공백·쉼표·순서까지 동일해야 하며, 안 맞으면 서명 실패 또는 설치 거부. + +**확정값** — [`Package.appxmanifest`](../../aluxlabs-link-win-msix/Package.appxmanifest)의 `Publisher`는 인증서 Subject에 맞춰져 있다. 콤마가 값 안에 있어 XML에서는 따옴표를 `"`로 이스케이프한다: + +```xml + +``` + +- `Publisher`(서명 신원)는 인증서와 일치 — **변경 금지**(바꾸면 패키지 신원이 바뀌어 자동 업데이트 끊김). +- 사용자에게 보이는 발행자 이름은 별개인 `ALUX Inc.` (브랜드명, sideload에서는 인증서와 무관). +- `.appinstaller`의 `Publisher`도 같은 값으로 맞춰져 있다 (4절). + +> 인증서 Subject 재확인이 필요하면: `certutil -user -store My` 또는 SafeNet Authentication Client에서 인증서 보기. + +## 3. MSIX 서명 켜기 (wapproj 설정) + +현재 [`aluxlabs-link-win-msix.wapproj`](../../aluxlabs-link-win-msix/aluxlabs-link-win-msix.wapproj) 는 **서명 OFF + 임시 인증서** 상태: + +```xml +false +True +``` + +배포 빌드에서는 임시 인증서 대신 실제 OV 토큰으로 서명한다. 권장 방식은 **빌드는 서명 없이(`AppxPackageSigningEnabled=false`) 번들만 만들고, 빌드 후 `signtool`로 별도 서명**하는 것 (토큰 비밀번호 입력 시점을 분리할 수 있어 CI/수동 모두 유연). + +VS GUI로 할 경우: wapproj 우클릭 → **게시(Publish) → 앱 패키지 만들기** 마법사에서 토큰 인증서를 선택해 서명할 수도 있다. + +## 4. 자동 업데이트 — `.appinstaller` (App Installer) + +별도 업데이트 서버/백엔드 로직이 **필요 없다.** Windows 내장 App Installer가 버전 비교·다운로드·적용을 모두 처리한다. 우리는 **정적 파일만 호스팅**한다. + +### 동작 흐름 + +1. 사용자는 `.msixbundle`이 아니라 **`.appinstaller` URL로 최초 설치**한다. +2. App Installer가 해당 `.appinstaller` URI를 기억한다. +3. 앱 실행 시(또는 백그라운드 작업) Windows가 `.appinstaller`를 다시 받아 **`Version`과 설치된 버전을 스스로 비교**한다. +4. 더 높으면 새 번들을 받아 적용한다. + +### `.appinstaller` 파일 (템플릿에서 자동 생성) + +`make`가 staging 된 번들 파일명에서 버전을 읽어 prod/dev 두 파일을 생성한다(수동 편집 없음). 정본은 템플릿이다: + +- 템플릿: [`AluxLabsLink.appinstaller.template`](../../aluxlabs-link-win-msix/AluxLabsLink.appinstaller.template) — 호스트/버전/번들 placeholder +- 생성물(gitignore): `dist/upload/AluxLabsLink.appinstaller` (prod) / `dist/upload/AluxLabsLink.dev.appinstaller` (dev) +- 생성: `make appinstaller` (또는 `make sync-s3`/`sync-s3-dev` 가 업로드 직전 자동 생성) + +스키마는 `2017/2` (Windows 1809+ 호환 — 매니페스트 MinVersion과 동일). `Publisher`는 인증서 Subject와 일치. + +### 버전 — 한 곳만 (Version.props) + +`.appinstaller`의 버전·번들 파일명은 **빌드된 번들과 자동으로 일치**한다 — `make`가 staging 된 번들명(`AluxLabs-Link-<버전>.msixbundle`)에서 버전을 그대로 주입하기 때문. 손으로 맞출 곳은 없다. + +릴리스 버전(Major.Minor.Patch)은 **`SharedProps/Version.props` 한 곳**이 단일 소스다(`ScratchVersion.targets`가 읽어 assembly·매니페스트·번들명에 전파). 4번째 Build 자리는 커밋 수로 자동. + +```powershell +make set-version VERSION=1.2.0 # 또는 make release-patch / release-minor +make show-version # 산출될 quad 확인 +``` + +> **``의 `Uri`(고정 URL)는 불변** — 설치된 클라이언트가 기억하는 진입점이다. 템플릿에 고정돼 있고, 버전·번들명만 주입된다. + +빌드된 번들의 실제 버전·Publisher 확인: + +```powershell +Get-AppLockerFileInformation -Path .\AluxLabs-Link-x.y.z.msixbundle | Select-Object -ExpandProperty Publisher +``` + +### 호스팅 — `scratch-link.aluxcoding.com` 루트 (확정) + +토큰 배포는 **`scratch-link.aluxcoding.com`(prod) / `dev-scratch-link.aluxcoding.com`(dev) 루트**에 `aws s3 cp`로 수동 업로드한다. (이 도메인만 CloudFront로 공개 서빙됨 — `scratch-assets`는 공개 DNS가 없어 제외.) + +``` +scratch-link.aluxcoding.com/ + AluxLabsLink.appinstaller # 고정 URL (진입점, 불변) + AluxLabs-Link-x.y.z.msixbundle # 토큰 서명된 번들 (버전별) +``` + +진입점 URL: `https://scratch-link.aluxcoding.com/AluxLabsLink.appinstaller` + +- **`.appinstaller` URL은 영원히 고정**. `.msixbundle` URL은 버전마다 바뀌어도 됨. +- **MIME 타입 필수** — 콘솔 업로드는 `binary/octet-stream`이 붙어 깨진다. 반드시 `--content-type` 지정: + - `.appinstaller` → `application/appinstaller` + - `.msixbundle` → `application/vnd.ms-appx` +- 업로드 후 **CloudFront 무효화** 필수 (안 하면 옛 캐시가 잘못된 MIME로 남음). + - 배포 ID: prod `E3HEXR4KAZLITV`, dev `E1WMSQXPP9L5YF` + +업로드 + 무효화 명령 (CLI 자격증명 필요 — IAM 정책 `scripts/aws/policies/iam-policy.json.tpl`): + +```powershell +$v = "1.0.0.1028" # 실제 빌드 버전 +$b = "scratch-link.aluxcoding.com" # dev면 dev-scratch-link.aluxcoding.com +aws s3 cp "dist\upload\AluxLabs-Link-$v.msixbundle" "s3://$b/AluxLabs-Link-$v.msixbundle" --content-type application/vnd.ms-appx --cache-control "public, max-age=31536000, immutable" +aws s3 cp "dist\upload\AluxLabsLink.appinstaller" "s3://$b/AluxLabsLink.appinstaller" --content-type application/appinstaller --cache-control "public, max-age=300" +aws cloudfront create-invalidation --distribution-id E3HEXR4KAZLITV --paths "/AluxLabsLink.appinstaller" "/AluxLabs-Link-$v.msixbundle" +``` + +검증 (HTTP HEAD로 Content-Type 확인): +```powershell +Invoke-WebRequest -Method Head "https://scratch-link.aluxcoding.com/AluxLabsLink.appinstaller" -UseBasicParsing | % { $_.Headers['Content-Type'] } +``` + +## 5. 신규 버전 릴리스 체크리스트 (토큰 수동) + +1. [ ] `make set-version VERSION=x.y.z` (또는 release-patch/minor) — 버전 단일 소스 갱신 +2. [ ] 토큰 연결 + SafeNet 클라이언트 실행 확인 +3. [ ] Release 구성으로 `.msixbundle` 빌드 (self-contained x86|x64) → `AluxLabs-Link-x.y.z.<커밋수>.msixbundle` +4. [ ] `signtool`로 서명 — **`/sha1 <썸프린트>` 권장** (`/n` 이름 매칭은 간헐 실패) +5. [ ] `signtool verify /pa`로 서명 검증 +6. [ ] 서명된 번들을 `dist/upload/`로 복사 +7. [ ] `make sync-s3` (dev면 `sync-s3-dev`) — appinstaller 자동 생성 + 업로드 + CloudFront 무효화 +8. [ ] HTTP HEAD로 Content-Type 검증 + 기존 설치본 자동 업데이트 확인 diff --git a/Documentation/Alux/KnownIssues.md b/Documentation/Alux/KnownIssues.md new file mode 100644 index 00000000..2de37e02 --- /dev/null +++ b/Documentation/Alux/KnownIssues.md @@ -0,0 +1,164 @@ +# 알려진 이슈 — Deployment 관련 + +본 문서는 2026-05-26 리브랜드(`feature/rebrand-aluxlabs-link`) 시점에 deployment 검증 중 발견된 이슈와 검증 결과를 기록한다. **출하 형식·시점·코드 서명 정책 결정 시 참고용**. + +마지막 검증 commit: `5209ce6 chore(msix): publish profile 을 self-contained 로 변경` +검증 환경: Windows 11 25H2 build 26200 (개발 PC, 정상 PC 동일 build). + +--- + +## 1. Tooltip 미표시 (H.NotifyIcon.WinUI 라이브러리 이슈) + +### 증상 +트레이 아이콘 위에 마우스 호버 시 풍선 tooltip 이 표시되지 않는다. + +### 영향 범위 +**Unpackaged 모드 (F5 디버그 / Release portable EXE) 에서만 발생**. Packaged 모드 (MSIX-installed) 에서는 정상 동작. + +원본 Scratch Link 가 packaged 형태로 MS Store 에서 배포되어 동작하는 것은 이 패턴과 일치. + +### 검증 매트릭스 +| 시나리오 | Tooltip 동작 | +|---|---| +| F5 디버그 (unpackaged) | ✗ 안 뜸 | +| Release self-contained portable EXE 직접 실행 | ✗ 안 뜸 | +| MSIX install (packaged) | (실행 자체 별도 이슈로 미검증, 원본 Scratch Link 는 정상 동작) | +| 7b4c335 (pre-.NET-8 시점) F5 빌드 | ✗ 안 뜸 — 우리 fork 변경 이전부터 동일 | +| 다른 PC 의 원본 Scratch Link 1.4.3.0 (MS Store install) | ✓ 정상 | + +### 시도한 해결책 (모두 실패) +- XAML `ToolTipText` 명시 설정 — 이미 적용돼 있음. 반영 안 됨. +- 런타임에 `trayIcon.ToolTipText` 재할당 (`ForceCreate` 전/후 모두 시도). 값은 .NET property 레벨에서 변경되나 Windows shell 의 NOTIFYICONDATA 에는 반영 안 됨. +- `UpdateToolTip()` 메서드 호출 시도 — public API 에 노출되지 않음 (reflection 으로 메서드 목록 조사 완료, `UpdateIcon` 만 존재). +- NuGet 1.8.260508005 → 1.8.250907003 다운그레이드 — 효과 없음. +- Explorer.exe 재시작 (tray cache flush) — 효과 없음. +- Ghost 패키지 (`ScratchFoundation.1711508CFD202 1.0.0.0`) 제거 — 다른 이슈 해결됐으나 tooltip 영향 없음. + +### 추정 원인 +`H.NotifyIcon.WinUI` 2.0.108 의 ToolTipText property setter 가 Shell_NotifyIcon(NIM_MODIFY) 호출 시 `NIF_TIP` 플래그를 누락하거나, NIM_MODIFY 자체를 보내지 않는 라이브러리 버그. + +### 출하 영향 +**출하 차단 안 함**. 학원/학교 사용자에게 보이는 화면 (트레이 아이콘 우클릭 메뉴) 은 정상 동작하며, 메뉴의 첫 항목이 "AluxLabs Link " 으로 표시되어 식별 가능. + +### 향후 검토 +- H.NotifyIcon.WinUI 2.x 의 더 새 버전 (2.0.110 이후) 시도 — 1809 호환 유지 확인 필수 +- 라이브러리 교체 (H.NotifyIcon 의 `TrayToolTip` element 사용 또는 P/Invoke Shell_NotifyIcon 직접 호출) +- 사용자 피드백이 명시적으로 요구하지 않으면 우선순위 낮음 + +--- + +## 2. MSIX packaged 모드에서 시작 시 즉시 크래시 (Win11 25H2 특이성 추정) + +### 증상 +MSIX 로 packaged install 후 시작 메뉴에서 실행 시 트레이 아이콘이 등장하지 않고 즉시 종료. Event Log 에 다음 정보: + +``` +Faulting application: AluxLabs Link.exe v1.0.0.x +Faulting module: Microsoft.UI.Xaml.dll v3.1.8.0 (번들된 DLL) +Exception: 0xc000027b (STATUS_FATAL_USER_CALLBACK_EXCEPTION) +WER P5: combase.dll +WER P8: 0x80040111 (REGDB_E_CLASSNOTREG) +``` + +### 영향 범위 +- 개발 PC: Windows 11 25H2 build 26200 — 크래시 재현 +- 정상 PC 에서의 packaged install 검증 미완료 (cert 신뢰 단계에서 막혀 실제 install 까지 못 감) +- **Unpackaged 형태 (F5 / Release portable EXE) 는 정상 동작 — 정상 PC 와 dev PC 모두에서 검증됨** + +### 추정 원인 +WinUI 3 self-contained 패키징의 알려진 한계 — XAML metadata / COM 클래스 등록의 일부가 시스템 레지스트리에 의존. 번들된 DLL 의 클래스를 활성화하려 할 때 시스템 레지스트리에서 매칭되는 항목을 못 찾아 `REGDB_E_CLASSNOTREG` 발생. + +Windows 11 25H2 (build 26200) 의 특이성일 가능성도 배제 못 함. 동일 build 의 정상 PC 검증 미완. + +### 시도한 해결책 +- NuGet WindowsAppSDK 1.8.260508005 → 1.8.250907003 다운그레이드: 동일 크래시 (timestamp 만 바뀜) +- self-contained 활성화 (`true`, `true` in pubxml): 같은 크래시 +- Ghost 패키지 (`ScratchFoundation.1711508CFD202`) 제거: 원본 Scratch Link 설치 문제는 해결됐으나 우리 빌드의 크래시는 별개 +- .NET 6 + WAS 1.3 으로 stack 회귀 시도: **빌드 환경 비호환** — 옛 WAS NuGet 의 build target 이 .NET 10 SDK + VS 2026 (v18.0) 환경의 path 와 매칭 안 됨. WAS 1.5, 1.6 도 동일 결과. + +### 출하 영향 +- **Portable EXE 배포 (MSIX 없이) → 영향 없음** (검증 완료) +- **MSIX 사이드로드 배포 → 위험** (이 이슈 미해결 시 사용자 PC 에서도 같은 크래시 가능성) +- **MS Store 배포 → 미검증** (Partner Center 심사 환경에서 실행 시도 → 거기서 결과 판명) + +### 향후 검토 +1. 정상 PC 에서 우리 .msixbundle 의 진짜 install + 실행 검증 (cert 수동 import 통과 후) +2. 동일 build 의 다른 OS (24H2, Win10 22H2) 에서 검증 +3. 위 결과에 따라: + - 정상 PC 에서 동작 → dev PC 25H2 특이성 확정, 일반 사용자엔 OK + - 정상 PC 에서도 크래시 → 우리 빌드의 packaged 모드 호환 문제, 더 깊은 디버그 필요 + +--- + +## 3. Ghost 패키지로 인한 원본 Scratch Link 설치 차단 (해결됨) + +### 증상 +개발 PC 에서 MS Store 에서 원본 Scratch Link 설치 시도 시 실패. 정상 PC 에서는 정상. + +### 원인 +리브랜드 이전에 빌드/배포된 옛 fork 버전이 원본의 `ScratchFoundation.1711508CFD202` Identity 로 dev PC 에 등록돼 있었음. 자체 서명 cert 로 서명된 그 ghost 가 MS-signed 정식 release 의 install 을 Identity name 충돌로 차단. + +### 해결 +```powershell +Get-AppxPackage -AllUsers *ScratchFoundation* | Remove-AppxPackage -AllUsers +``` + +리브랜드 commit `53bfd57` (MSIX Package Identity → `ALUXInc.AluxLabsLink`) 이후로는 새 빌드가 이 Identity 를 더 이상 사용하지 않으므로 같은 문제 재발하지 않음. + +### 출하 영향 +없음. 과거 dev install 의 환경 정리 이슈로 해결됨. + +--- + +## 4. 검증된 사실 — 출하 결정 시 신뢰 가능 + +| 항목 | 상태 | +|---|---| +| 리브랜드 (식별자/이름/manifest/네임스페이스/폴더/문서) | ✅ 완료 (commit `7684c1c` 까지) | +| MSIX Identity 충돌 (Publisher CN, ScratchFoundation 잔존) | ✅ 해결 (commit `7e9f28b`) | +| Self-contained pubxml 설정 | ✅ 적용 (commit `5209ce6`) | +| Release self-contained portable EXE 빌드 | ✅ 성공 (`dotnet publish -c Release_Win -r win-x64 --self-contained true`) | +| Portable EXE 동작 (dev PC, Win11 25H2) | ✅ 트레이 정상 등장 | +| Portable EXE 동작 (정상 PC, Win11 25H2) | ✅ 트레이 정상 등장 | +| Tooltip 동작 (unpackaged) | ❌ Issue #1 deferred | +| MSIX install + 실행 (dev PC) | ❌ Issue #2 — 정상 PC 미검증 | + +--- + +## 5. 출하 형식 결정용 비교 + +| 출하 형식 | 1809 호환 | 코드 서명 | 사용자 UX | 현재 검증 상태 | +|---|---|---|---|---| +| Portable EXE + ZIP | ✓ | ⚠️ EXE 직접 서명 가능 | 압축 풀고 실행 (시작 메뉴 등록 X) | ✅ 동작 확인 | +| Inno Setup / NSIS installer | ✓ | ✓ 표준 .exe 서명 | "다음 → 완료" 마법사 | 미시도 | +| MSIX 사이드로드 | ✓ (이론) | ✓ 자체 cert 또는 EV/OV | 자체 서명 cert 신뢰 등록 필요 | Issue #2 미해결 | +| MS Store | ✓ | MS 가 자동 서명 | Store 에서 "Install" 한 번 | 미등록 | + +### 권장 출하 path +1. **단기 (학원 직배포)**: 코드 서명된 Inno Setup installer — Issue #2 우회, 가장 안정. **MSIX 의 알려진 한계 회피**. +2. **중기 (대규모 보급)**: MS Store 등록 검토 — MS 가 서명/runtime/업데이트 자동 처리. Issue #2 의 실제 영향은 Store 심사 단계에서 결과 확정. +3. **소규모 dev/베타**: Portable ZIP — 임시 검증용 + +--- + +## 6. 회귀 시도 (실패) — 향후 같은 시도 반복 방지 + +`.NET 8` + `WindowsAppSDK 1.8` stack 을 원본 `.NET 6` + `WindowsAppSDK 1.3` 으로 회귀 시도했으나 다음 이유로 빌드 자체 실패: + +- 옛 `Microsoft.WindowsAppSDK` NuGet (1.3, 1.5, 1.6 모두) 의 `MrtCore.PriGen.targets` 가 `Microsoft\VisualStudio\v17.0\AppxPackage\Microsoft.Build.Packaging.Pri.Tasks.dll` 경로를 가정하는데, 우리 환경 (.NET 10 SDK 10.0.300 + VS 2026 build 18.0) 의 실제 path 구조와 불일치. +- 진짜 stack 회귀하려면 **빌드 환경까지 회귀** (VS 2022 설치 + .NET 6 SDK 강제) 가 필요. 작업량 크고 다른 호환성 이슈 사슬 가능성. + +따라서 stack 회귀는 **포기**. 현재 `.NET 8` + `WindowsAppSDK 1.8.260508005` stack 으로 출하 형식을 결정하는 방향. + +--- + +## 7. 미커밋 변경 (회귀 시도) — 모두 revert 완료 + +본 문서 작성 시점 (commit `5209ce6` 직후) 에 회귀 시도로 한 다음 변경들은 **모두 `git restore .` 로 revert** 했다. 작업 트리 clean 상태: + +- `SharedProps/WindowsSDK.props`: WAS 1.8 → 1.3/1.5/1.6 (revert) +- `aluxlabs-link-win/aluxlabs-link-win.csproj`: net8.0 → net6.0, RuntimeIdentifiers win10- prefix (revert) +- 3 pubxml: self-contained=false (revert) +- `aluxlabs-link-win-msix/aluxlabs-link-win-msix.wapproj`: AssetTargetFallback net6.0 (revert) + +git log 에 이 회귀 시도는 흔적 남지 않음. diff --git a/Documentation/Alux/RebrandingPlan.md b/Documentation/Alux/RebrandingPlan.md new file mode 100644 index 00000000..2a6848f9 --- /dev/null +++ b/Documentation/Alux/RebrandingPlan.md @@ -0,0 +1,381 @@ +# 리브랜딩 작업 계획서 — scratch-link → AluxLabs Link + +원본 `scratch-link` (Scratch Foundation, AGPL-3.0) 의 Windows 포크를 **"AluxLabs Link"** 라는 독립 제품으로 분리하기 위한 전수 변경 목록. + +## 1. 목표와 결정 사항 + +| 항목 | 결정값 | 비고 | +|---|---|---| +| 사용자 표시명 | **AluxLabs Link** | 트레이, 인스톨러, About 등 모든 UI | +| 회사명 | ALUX, Inc. | 이미 적용된 상태 | +| 상표 회피 | 제품명에 "Scratch" 단어 **사용 금지** | nominative fair use 도 안전 마진 위해 회피 | +| Scratch 호환성 표현 | 문서에 한정해 "Scratch 와 호환됨" 정도만 | "for Scratch" / "Scratch-compatible" 같이 endorsement 로 읽히는 표현 회피 | +| 라이선스 | AGPL-3.0-only 유지 | 원본과 동일. 파생 저작물 의무 준수 | +| 원본 attribution | 모든 파일의 `// Copyright (c) Scratch Foundation` 헤더 **보존** | AGPL §5 요구 | + +### 1.1 식별자 매핑 (소스 of truth) + +| 종류 | 기존 | 신규 | +|---|---|---| +| 사용자 표시명 (Display) | `Alux Scratch Link` / `scratch-link` | `AluxLabs Link` | +| 어셈블리명 (`AssemblyName`) | `Alux Scratch Link` | `AluxLabs Link` | +| 루트 네임스페이스 | `ScratchLink` | `AluxLabs.Link` | +| Windows 네임스페이스 | `ScratchLink.Win` | `AluxLabs.Link.Win` | +| 핵심 클래스 | `ScratchLinkApp` | `AluxLabsLinkApp` | +| 솔루션 파일 | `scratch-link.sln` | `aluxlabs-link.sln` | +| 폴더 (Windows 본체) | `scratch-link-win/` | `aluxlabs-link-win/` | +| 폴더 (공통 코드) | `scratch-link-common/` | `aluxlabs-link-common/` | +| 폴더 (MSIX) | `scratch-link-win-msix/` | `aluxlabs-link-win-msix/` | +| 프로젝트 파일 | `scratch-link-win.csproj` 등 | `aluxlabs-link-win.csproj` 등 | +| 아이콘 파일 | `scratch-link.ico` / `scratch-link-tray.ico` | `aluxlabs-link.ico` / `aluxlabs-link-tray.ico` | +| MSIX Package Identity `Name` | `ScratchFoundation.1711508CFD202` | `ALUXInc.AluxLabsLink` (임시. Partner Center 등록 시 발급값으로 교체) | +| MSIX Package Identity `Publisher` | `CN=2EC43DF1-469A-4119-9AB9-568A0A1FF65F` | 서명 인증서 Subject 의 CN (자체 서명 cert 또는 Store 발급값) | +| WebSocket 포트 | 20211 (변경 없음) | 동일 — Scratch 와 연결되는 endpoint | +| WebSocket path (`/scratch/ble` 등) | 변경 없음 | 동일 — Scratch 의 클라이언트 API 규약 | + +## 2. 절대 변경 금지 (AGPL §5 / 상표 표시) + +다음 항목은 라이선스/상표 의무 때문에 **건드리면 안 된다**. + +| 항목 | 위치 | 이유 | +|---|---|---| +| AGPL 라이선스 전문 | `LICENSE` | AGPL §5 — 라이선스 텍스트 동봉 의무 | +| 상표 정책 문서 | `TRADEMARK` | Scratch Foundation 상표권 명시 — 삭제 시 법적 분쟁 위험 | +| 파일 헤더 `// ` | 모든 원본 유래 `.cs` | AGPL §5 — 원저작자 표시 보존 | +| `// Copyright (c) Scratch Foundation. All rights reserved.` | 모든 원본 유래 `.cs` | 동일 | +| `// Based on scratch-link by Scratch Foundation, licensed under AGPL-3.0-only.` | ALUX 신규 작성 파일의 헤더 | 이미 정확한 attribution. 유지 | +| 프로토콜 식별자 문자열 | `/scratch/ble`, `/scratch/bt`, `/scratch/serial` (WebSocket path) | Scratch 클라이언트와의 wire-level 호환성 | +| 프로토콜 문서 | `Documentation/Architecture.md`, `Documentation/BluetoothLE.md`, `Documentation/Bluetooth.md`, `Documentation/NetworkProtocol.md`, `Documentation/TestPlans.md` | 원본 프로토콜 명세 — 사실상 historical reference. "Scratch Link" 단어를 protocol 명칭으로 보고 그대로 둠 | +| `Documentation/Alux/SerialApiReference.md` 등에서 protocol 을 가리키는 "Scratch Link" 언급 | 동일 docs 일부 | 같은 이유. 단 우리 제품을 가리키는 부분은 변경 | +| 코드 안 doc comment 의 "Scratch Link protocol" / "Scratch Link sessions" | `Session.cs:28,33`, `EncodingHelpers.cs:14,15`, `BLESession.cs:52`, `ScratchLinkApp.cs:13` 등 | 프로토콜의 일반명칭으로 해석. 변경 시 `Scratch Link 프로토콜` 등으로 명시화 가능 (선택) | + +### 2.1 신규 추가 권장 (AGPL §5) + +- **`NOTICE` 파일 신규 작성** — fork 출처와 변경자 명시. 본문 예시는 §7 참조 +- 기존 원본 파일을 ALUX 가 **상당히 수정**한 경우 헤더 아래 한 줄 추가 (선택): + `// Modified by ALUX, Inc. on 2026-MM-DD: <간단한 사유>` + +## 3. 작업 범위 — 포함 / 제외 + +### 3.1 포함 (Windows 빌드 체인) + +`scratch-link.sln` 에 포함되고 Windows 빌드에 영향: + +- 루트 파일: `LICENSE`, `TRADEMARK`, `README.md`, `package.json`, `Makefile`, `playground.html`, `playground.js`, `.editorconfig`, `stylecop.json`, `release.config.js`, `renovate.json5`, `global.d.ts` +- `scratch-link-common/` (`.shproj`, `.projitems`, 모든 `.cs`) +- `scratch-link-win/` (`.csproj`, `.xaml`, 모든 `.cs`, `app.manifest`, 아이콘) +- `scratch-link-win-msix/` (`.wapproj`, `Package.appxmanifest`, 이미지) +- `SharedProps/` (`.props`, `.targets`) +- `Documentation/Alux/` 전체 +- `.github/actions/windows-build/action.yml` +- `brand/build_icons.py` +- `CLAUDE.md` + +### 3.2 제외 (이번 작업에서 손대지 않음) + +| 항목 | 이유 | +|---|---| +| `scratch-link-mac/` 전체 | Mac 빌드 안 함. 솔루션에 "Unsupported" 로만 표시 | +| `Scratch Link Safari Helper/` 전체 | Mac Safari 확장. Windows 무관 | +| `scratch-link/` (MAUI 폴더) | 솔루션에서 빠진 레거시 코드. 별도 정리 권장 | +| `fastlane/` | Mac 서명 자동화 | +| `bin/`, `obj/`, `.vs/`, `*.user` | 자동 생성. 빌드 시 재생성 | +| `Scratch Link Safari Helper/` 안의 모든 파일명 | Mac 전용 | +| `.github/actions/macos-build/action.yml` | Mac CI | +| `Documentation/Architecture.md` 등 upstream 원본 문서 | §2 — 프로토콜 명세, AGPL attribution | + +> Mac 프로젝트는 같은 `scratch-link-common` 을 import 하기 때문에, common 폴더/파일명을 바꾸면 `scratch-link-mac.csproj:212` 의 `Import Project="..\scratch-link-common\scratch-link-common.projitems"` 가 깨진다. Mac 은 어차피 안 빌드되므로 무시 가능하지만, 정리 차원에서 같이 업데이트하거나 솔루션에서 Mac 프로젝트를 빼는 것도 검토. + +## 4. 작업 순서 (의존성 고려) + +순서 잘못 잡으면 빌드가 깨지거나 식별자 충돌이 난다. 권장 순서: + +| 단계 | 작업 | 빌드 영향 | +|---|---|---| +| 1 | MSIX Identity 임시값으로 변경 (cert 결정 전이라도 `ALUXInc.AluxLabsLink` + `CN=ALUX, Inc.` 자체 서명 임시 cert) | MSIX 빌드만 영향. EXE 빌드 무관 | +| 2 | UI 노출 문자열 변경 (DisplayName, ToolTip, About) | 빌드 영향 미미 | +| 3 | NOTICE 파일 신규 작성 + README 어트리뷰션 보강 | 빌드 무관 | +| 4 | `AssemblyName` / `RootNamespace` 변경 → `bin/obj` 전체 삭제 후 재빌드 | csproj 단위 | +| 5 | 모든 `.cs` 의 `namespace`, `using` 일괄 치환 (`ScratchLink` → `AluxLabs.Link`) | 빌드 깨짐 → 일관 치환 후 회복 | +| 6 | 클래스 `ScratchLinkApp` → `AluxLabsLinkApp` 리네임 | 빌드 깨짐 → 사용처 동시 치환 | +| 7 | XAML 의 `x:Class`, `xmlns:local` 갱신 | XAML 컴파일 | +| 8 | `.cs` 파일명 변경 (`ScratchLinkApp.cs` → `AluxLabsLinkApp.cs`) | 무영향 (csproj 가 와일드카드 include 면) | +| 9 | 아이콘 파일명 변경 + csproj 의 `Content Include` / `ApplicationIcon` 동시 갱신 | 빌드 | +| 10 | 프로젝트 파일명 변경 (`*.csproj`, `*.wapproj`, `*.shproj`, `.projitems`) + `.sln` 의 경로 동시 갱신 (ProjectGuid 보존) | 솔루션 로드 | +| 11 | 폴더명 변경 + `.sln` / csproj 의 모든 `..\scratch-link-*\` 경로 갱신 | 솔루션 | +| 12 | 솔루션 파일명 변경 (`scratch-link.sln` → `aluxlabs-link.sln`) | 마지막 | +| 13 | `Documentation/Alux/*.md`, `CLAUDE.md`, `README.md`, `.github/actions/windows-build/action.yml` 의 경로/이름 참조 갱신 | 문서 | +| 14 | 전체 빌드 검증 (Debug_Win / Release_Win 양쪽) | 최종 | + +> **VS 의 리팩토링 기능 우선 활용**: 5~7 단계는 Visual Studio 의 "Rename" (F2) 가 가장 안전. namespace 변경 시 VS 가 `using` 까지 자동 갱신. sed 일괄 치환은 마지막 보루. + +> **Git 커밋 분리 권장**: 단계별로 커밋. 한 커밋에 모두 몰면 충돌 시 분리 불가. 권장 단위: (a) MSIX identity 만, (b) UI 문자열 만, (c) AssemblyName/네임스페이스, (d) 파일/폴더 rename, (e) 문서 갱신. + +## 5. 파일별 변경 목록 + +### 5.1 MSIX Identity (Tier A — 최우선) + +#### [scratch-link-win-msix/Package.appxmanifest](../../scratch-link-win-msix/Package.appxmanifest) + +| 라인 | 현재 | 변경 | +|---|---|---| +| 10 | `Name="ScratchFoundation.1711508CFD202"` | `Name="ALUXInc.AluxLabsLink"` (Store 발급 시 교체) | +| 11 | `Publisher="CN=2EC43DF1-469A-4119-9AB9-568A0A1FF65F"` | 서명 인증서 Subject CN 으로 교체 | +| 15 | `Alux Scratch Link` | `AluxLabs Link` | +| 16 | `ALUX, Inc.` | (그대로) | +| 34 | `DisplayName="Alux Scratch Link"` | `DisplayName="AluxLabs Link"` | +| 35 | `Description="Alux Scratch Link"` | `Description="AluxLabs Link"` | + +#### [scratch-link-win/app.manifest](../../scratch-link-win/app.manifest) + +| 라인 | 현재 | 변경 | +|---|---|---| +| 3 | `name="Alux Scratch Link.app"` | `name="AluxLabs Link.app"` | + +### 5.2 UI 노출 문자열 (Tier B) + +#### [scratch-link-win/TrayIcon.xaml](../../scratch-link-win/TrayIcon.xaml) + +| 라인 | 현재 | 변경 | +|---|---|---| +| 7 | `xmlns:local="using:ScratchLink.Win"` | `xmlns:local="using:AluxLabs.Link.Win"` | +| 10 | `x:Key="ScratchLinkTaskbarIcon"` | `x:Key="AluxLabsLinkTaskbarIcon"` (App.xaml.cs:95 도 동시 갱신) | +| 12 | `ToolTipText="Alux Scratch Link"` | `ToolTipText="AluxLabs Link"` | +| 14 | `IconSource="scratch-link-tray.ico"` | `IconSource="aluxlabs-link-tray.ico"` | +| 26 | `Label="Alux Scratch Link 1.0.0.0"` | `Label="AluxLabs Link 1.0.0.0"` | + +### 5.3 csproj / 어셈블리 메타데이터 (Tier B) + +#### [scratch-link-win/scratch-link-win.csproj](../../scratch-link-win/scratch-link-win.csproj) + +| 라인 | 현재 | 변경 | +|---|---|---| +| 7 | `ScratchLink.Win` | `AluxLabs.Link.Win` | +| 8 | `Alux Scratch Link` | `AluxLabs Link` | +| 21 | `scratch-link.ico` | `aluxlabs-link.ico` | +| 23 | `Import Project="..\scratch-link-common\scratch-link-common.projitems"` | 폴더/파일 리네임 후 `..\aluxlabs-link-common\aluxlabs-link-common.projitems` | +| 37 | `` | `` | +| 38 | `` | `` | + +#### [scratch-link-win-msix/scratch-link-win-msix.wapproj](../../scratch-link-win-msix/scratch-link-win-msix.wapproj) + +| 라인 | 현재 | 변경 | +|---|---|---| +| 51 | `..\scratch-link-win\scratch-link-win.csproj` | `..\aluxlabs-link-win\aluxlabs-link-win.csproj` | +| 99 | `` | `..\aluxlabs-link-win\aluxlabs-link-win.csproj` | + +#### [SharedProps/ScratchVersion.targets](../../SharedProps/ScratchVersion.targets) + +| 라인 | 현재 | 변경 | +|---|---|---| +| 47 | 코멘트: `"Alux Scratch Link 1.0.0.x"` | `"AluxLabs Link 1.0.0.x"` | + +> 파일명 `ScratchVersion.targets` 자체는 MSBuild target name 이므로 굳이 안 바꿔도 됨. 바꾸려면 `AluxLabsVersion.targets` 로 변경하고 모든 `` 갱신. + +### 5.4 C# 네임스페이스 일괄 치환 (Tier C — 가장 큰 작업) + +**치환 규칙**: + +| 기존 | 신규 | +|---|---| +| `namespace ScratchLink;` | `namespace AluxLabs.Link;` | +| `namespace ScratchLink.Win;` | `namespace AluxLabs.Link.Win;` | +| `namespace ScratchLink.Win.BLE;` | `namespace AluxLabs.Link.Win.BLE;` | +| `namespace ScratchLink.Win.BT;` | `namespace AluxLabs.Link.Win.BT;` | +| `namespace ScratchLink.Win.Serial;` | `namespace AluxLabs.Link.Win.Serial;` | +| `namespace ScratchLink.BLE;` | `namespace AluxLabs.Link.BLE;` | +| `namespace ScratchLink.BT;` | `namespace AluxLabs.Link.BT;` | +| `namespace ScratchLink.Serial;` | `namespace AluxLabs.Link.Serial;` | +| `namespace ScratchLink.JsonRpc;` | `namespace AluxLabs.Link.JsonRpc;` | +| `namespace ScratchLink.JsonRpc.Converters;` | `namespace AluxLabs.Link.JsonRpc.Converters;` | +| `namespace ScratchLink.Extensions;` | `namespace AluxLabs.Link.Extensions;` | +| `using ScratchLink;` / `using ScratchLink.*;` | 모두 대응되는 `AluxLabs.Link*` 로 | +| 클래스 `ScratchLinkApp` | `AluxLabsLinkApp` | + +**영향 파일 목록** (전수, 약 50개 — `using` 만 갱신되는 케이스 포함): + +`scratch-link-common/`: +- ScratchLinkApp.cs (파일명도 변경 → AluxLabsLinkApp.cs) +- Session.cs +- SessionManager.cs +- PeripheralSession.cs +- WebSocketListener.cs +- EncodingHelpers.cs +- EventAwaiter.cs +- BLE/IBLEEndpoint.cs +- BLE/BLESession.cs +- BLE/GattHelpers.cs +- BT/BTSession.cs +- Serial/SerialSession.cs +- Serial/SerialOpenParams.cs +- Serial/SerialDiscoveryFilter.cs +- JsonRpc/JsonRpc2Message.cs +- JsonRpc/JsonRpc2Request.cs +- JsonRpc/JsonRpc2Response.cs +- JsonRpc/JsonRpc2Error.cs +- JsonRpc/JsonRpc2Exception.cs +- JsonRpc/Converters/JsonRpc2MessageConverter.cs +- JsonRpc/Converters/JsonRpc2ValueConverter.cs +- Extensions/ContainerExtensions.cs +- Extensions/JsonExtensions.cs +- Extensions/SemaphoreSlimExtensions.cs + +`scratch-link-win/`: +- App.xaml.cs (line 5, 11, 12, 27, 57, 95) +- App.xaml (line 5, 8 — `x:Class`, `xmlns:local`) +- TrayIcon.xaml (line 7 — `xmlns:local`) +- WinSessionManager.cs +- BLE/WinBLESession.cs +- BLE/WinBLEEndpoint.cs +- BLE/WinGattHelpers.cs +- BT/WinBTSession.cs +- Serial/WinSerialSession.cs +- Serial/WinSerialPortInfo.cs +- Serial/WinSerialPortEnumerator.cs + +`scratch-link-common/scratch-link-common.projitems`: +- 라인 9: `ScratchLink` → `AluxLabs.Link` +- 라인 30: `` → 파일명 변경 시 동시 갱신 + +### 5.5 파일명 변경 (Tier D) + +| 기존 | 신규 | +|---|---| +| `scratch-link-common/ScratchLinkApp.cs` | `aluxlabs-link-common/AluxLabsLinkApp.cs` | +| `scratch-link-common/scratch-link-common.shproj` | `aluxlabs-link-common/aluxlabs-link-common.shproj` | +| `scratch-link-common/scratch-link-common.projitems` | `aluxlabs-link-common/aluxlabs-link-common.projitems` | +| `scratch-link-win/scratch-link-win.csproj` | `aluxlabs-link-win/aluxlabs-link-win.csproj` | +| `scratch-link-win/scratch-link.ico` | `aluxlabs-link-win/aluxlabs-link.ico` | +| `scratch-link-win/scratch-link-tray.ico` | `aluxlabs-link-win/aluxlabs-link-tray.ico` | +| `scratch-link-win-msix/scratch-link-win-msix.wapproj` | `aluxlabs-link-win-msix/aluxlabs-link-win-msix.wapproj` | +| `scratch-link.sln` | `aluxlabs-link.sln` | + +### 5.6 폴더 변경 (Tier D) + +| 기존 | 신규 | +|---|---| +| `scratch-link-common/` | `aluxlabs-link-common/` | +| `scratch-link-win/` | `aluxlabs-link-win/` | +| `scratch-link-win-msix/` | `aluxlabs-link-win-msix/` | + +> 폴더 rename 시 `.sln` 의 모든 프로젝트 경로, 모든 csproj/projitems 의 `..\` 상대 경로, `.github/actions/windows-build/action.yml` 의 빌드 명령 경로 모두 동시 갱신 필요. ProjectGuid 는 **절대 바꾸지 말 것** — 솔루션이 GUID 로 프로젝트를 식별하기 때문. + +### 5.7 .sln 파일 (Tier E) + +#### [scratch-link.sln](../../scratch-link.sln) + +| 라인 | 변경 | +|---|---| +| 33 | `"scratch-link-common", "scratch-link-common\scratch-link-common.shproj", ...` → `"aluxlabs-link-common", "aluxlabs-link-common\aluxlabs-link-common.shproj", ...` (GUID 유지) | +| 53 | `"scratch-link-win", "scratch-link-win\scratch-link-win.csproj", ...` → `"aluxlabs-link-win", "aluxlabs-link-win\aluxlabs-link-win.csproj", ...` (GUID 유지) | +| 55 | `"scratch-link-win-msix", "scratch-link-win-msix\scratch-link-win-msix.wapproj", ...` → 동일 패턴 | +| 223~225 | `scratch-link-common\scratch-link-common.projitems*{guid}*SharedItemsImports` 경로 갱신 | + +> Mac 프로젝트 (`scratch-link-mac`, line 35) 는 그대로 두되, 안의 `Import Project="..\scratch-link-common\..."` 참조가 깨지므로 솔루션 빌드 시 unloaded 상태가 됨. Windows 빌드에는 영향 없음. + +### 5.8 GitHub Actions (Tier F) + +#### [.github/actions/windows-build/action.yml](../../.github/actions/windows-build/action.yml) + +| 라인 | 현재 | 변경 | +|---|---|---| +| 22 | `msbuild scratch-link-win-msix/scratch-link-win-msix.wapproj ...` | `msbuild aluxlabs-link-win-msix/aluxlabs-link-win-msix.wapproj ...` | +| 28 | `mv -v scratch-link-win-msix/AppPackages/scratch-link-win-msix_*_${{...}}.msixupload Artifacts/` | 경로/패턴 갱신 | +| 30 | `for PKGPATH in scratch-link-win-msix/AppPackages/scratch-link-win-msix_*_..._Win_Test/scratch-link-win-msix_*_..._Win.msixbundle; do` | 동일 | +| 33 | 정규식 `scratch-link-win-msix_([.0-9]+)_(.*)_..._Win.msixbundle$` | `aluxlabs-link-win-msix_...` | +| 39, 41 | `mv -v "$PKGPATH" "Artifacts/Scratch Link ${PKGVERSION}.msixbundle"` | `"Artifacts/AluxLabs Link ${PKGVERSION}.msixbundle"` | + +### 5.9 문서 / 메타데이터 (Tier F) + +| 파일 | 변경 사항 | +|---|---| +| [README.md](../../README.md) | 제목 `# Alux Scratch Link` → `# AluxLabs Link`. 본문의 "Alux Scratch Link" 모든 인스턴스. fork 출처 attribution 강화 (§7 NOTICE 텍스트 참조). 저장소 구조 트리의 폴더명 갱신. | +| [CLAUDE.md](../../CLAUDE.md) | 폴더명/프로젝트명 언급 갱신. `scratch-link-common`, `scratch-link-win`, `scratch-link-win-msix` → 신규 이름 | +| [Documentation/Alux/WindowsDevSetup-VS2026.md](WindowsDevSetup-VS2026.md) | 라인 3, 7, 9~12, 32, 54~56, 66, 68, 76~78, 88~89, 94~95 — 폴더/파일/제품명 갱신 | +| [Documentation/Alux/SerialKeepAliveGuide.md](SerialKeepAliveGuide.md) | 라인 5 의 "Scratch Link serial transport" — protocol 표현은 유지하거나 "AluxLabs Link 의 serial transport (Scratch Link serial protocol 구현)" 식으로 명확화 | +| [Documentation/Alux/SerialApiReference.md](SerialApiReference.md) | 라인 358 의 "Scratch Link does not retry..." → "AluxLabs Link does not retry..." (구현 동작 설명이므로 우리 제품명으로) | +| [package.json](../../package.json) | `"name": "alux-scratch-link"` → `"name": "aluxlabs-link"`. description 갱신 | +| [Makefile](../../Makefile) | `scratch-link` 관련 타겟 경로 갱신 (Windows 빌드에 직접 관여하지는 않음 — icons 등) | +| [brand/build_icons.py](../../brand/build_icons.py) | 출력 파일명 `scratch-link.ico` / `scratch-link-tray.ico` → `aluxlabs-link.ico` / `aluxlabs-link-tray.ico` | +| `playground.html` / `playground.js` | 원본 테스트 페이지. "Scratch Link" 단어가 *우리 앱*을 가리키는 부분만 갱신. 프로토콜 설명 부분은 유지 | + +## 6. 작업 후 검증 체크리스트 + +- [ ] `Documentation/Architecture.md`, `BluetoothLE.md`, `NetworkProtocol.md`, `TestPlans.md`, `Bluetooth.md` 의 원본 텍스트는 **변경되지 않았다** +- [ ] `LICENSE`, `TRADEMARK` 는 **변경되지 않았다** +- [ ] 모든 `.cs` 파일의 `// ` 헤더가 **유지되었다** +- [ ] `NOTICE` 파일이 새로 생성되었고 fork 출처가 명시되었다 +- [ ] `README.md` 에 fork 출처 + AGPL 라이선스 표시 + 상표 무관 disclaimer 가 있다 +- [ ] `grep -ri "Alux Scratch Link"` 결과 0건 (build 산출물 제외) +- [ ] `grep -ri "scratch-link"` 결과 — 원본 attribution 헤더와 프로토콜 명세 문서를 제외하면 0건 +- [ ] `grep -ri "ScratchLink"` 결과 — 위와 동일 기준 +- [ ] MSIX Package Identity 의 `Name`/`Publisher` 가 원본 ScratchFoundation 값이 **아니다** +- [ ] `dotnet build -c Debug_Win` 성공 +- [ ] `msbuild aluxlabs-link-win-msix/aluxlabs-link-win-msix.wapproj -p:Configuration=Release_Win -p:Platform=x64` 성공 +- [ ] 생성된 `.msixbundle` 파일명에 "AluxLabs Link" 가 들어가고 "Scratch" 가 들어가지 **않는다** +- [ ] MSIX 설치 후 시작 메뉴 / 트레이 / About 의 표시명이 모두 "AluxLabs Link" 다 +- [ ] 트레이 아이콘 우클릭 → 버전 복사 후 클립보드에 "AluxLabs Link" 가 들어 있다 +- [ ] 기존 PC 에 원본 Scratch Link 가 설치돼 있어도 충돌 없이 사이드바이사이드 설치된다 +- [ ] WebSocket 포트 20211, path `/scratch/ble`, `/scratch/bt`, `/scratch/serial` 가 그대로 동작한다 (Scratch 호환성) + +## 7. NOTICE 파일 신규 작성 (§2.1) + +`NOTICE` 파일을 저장소 루트에 신규 생성. 권장 내용: + +``` +AluxLabs Link +Copyright (c) 2026 ALUX, Inc. + +This product is derived from scratch-link by the Scratch Foundation +(https://github.com/scratchfoundation/scratch-link), originally licensed +under the GNU Affero General Public License v3.0 (AGPL-3.0-only). + +This product is also distributed under the AGPL-3.0-only license. +See the LICENSE file for the full license text. + +The following modifications have been made by ALUX, Inc.: + - Removed macOS support and Safari Helper extension + - Added USB Serial transport support + - Changed default WebSocket port to 20211 to allow coexistence with + the original Scratch Link on the same machine + - Upgraded to .NET 8 and Windows App SDK 1.8 + - (etc.) + +"Scratch" is a trademark of the Scratch Foundation. AluxLabs Link is +not affiliated with, endorsed by, or sponsored by the Scratch Foundation. +References to the "Scratch Link protocol" in source code documentation +refer to the network protocol established by the original scratch-link +project, used here for client compatibility. +``` + +README 상단에도 다음 블록을 추가 (이미 일부 표현 있음 — 통합/강화): + +```markdown +This is a Windows-only fork of [scratch-link](https://github.com/scratchfoundation/scratch-link) +by the Scratch Foundation, redistributed under the AGPL-3.0-only license. + +"Scratch" is a trademark of the Scratch Foundation. This product is not +affiliated with, endorsed by, or sponsored by the Scratch Foundation. +``` + +## 8. 리스크 / 함정 + +| 위험 | 대응 | +|---|---| +| ProjectGuid 변경으로 .sln 깨짐 | GUID 는 **유지**. 이름과 경로만 변경 | +| Mac 프로젝트 (`scratch-link-mac`) 의 `Import Project="..\scratch-link-common\..."` 경로 깨짐 | Windows 빌드 영향 없음. Mac 안 쓰면 무시 가능. 깔끔히 정리하려면 솔루션에서 Mac 프로젝트 제거 또는 동일 경로 갱신 | +| Visual Studio 캐시 (`.vs/`) 가 옛 경로 보존 | rename 후 `.vs/` 폴더 삭제 후 솔루션 재오픈 | +| `bin/obj` 의 옛 어셈블리명 산출물 잔존 | rename 후 두 폴더 모두 삭제 | +| MSIX 의 데이터 폴더 위치 변경 | `Identity Name` 이 바뀌면 `%LOCALAPPDATA%\Packages\` 경로가 새로 생김. 기존 데이터 마이그레이션 불필요 (개발 중인 fork 이므로) | +| GitHub Actions workflow 가 옛 경로로 실행되어 CI 실패 | `.github/actions/windows-build/action.yml` 의 경로/패턴 정규식 동시 갱신 후 push | +| 원본 Scratch Foundation 의 copyright header 를 실수로 제거 | grep 으로 사전 검증. `grep -rn "Copyright (c) Scratch Foundation"` 결과가 변경 전과 동일해야 함 | +| 프로토콜 doc comment 에서 "Scratch Link" 를 제품명인 줄 알고 변경 | §2 의 "프로토콜 식별자" 항목 참고. 모호하면 `Scratch Link protocol` 로 명시화 | +| Partner Center 등록 후 받은 Identity Name/Publisher 와 임시값 충돌 | Store 발급값을 받은 시점에 manifest 의 두 줄만 다시 교체. 다른 식별자 영향 없음 | + +## 9. Out-of-scope — 별도 작업 검토 + +- `scratch-link/` MAUI 폴더 제거 여부 (현재 솔루션에 포함 안 되지만 디스크에 잔존) +- `scratch-link-mac/` 솔루션에서 분리 또는 별도 저장소로 옮기기 +- `Scratch Link Safari Helper/` 폴더 통째 제거 +- `fastlane/` 폴더 제거 +- Documentation 폴더의 upstream 원본 문서들을 `Documentation/Upstream/` 같은 서브폴더로 정리 (구분 명확화) diff --git a/Documentation/Alux/ScratchVmInterop.md b/Documentation/Alux/ScratchVmInterop.md new file mode 100644 index 00000000..3cf4b752 --- /dev/null +++ b/Documentation/Alux/ScratchVmInterop.md @@ -0,0 +1,119 @@ +# scratch-vm 측 연동 식별자 변경 안내 + +본 문서는 `feature/rebrand-aluxlabs-link` 브랜치에서 진행된 AluxLabs Link 리브랜딩 과정에서 **scratch-vm 및 그 파생 라이브러리에 영향을 줄 수 있는 식별자 변경**을 정리한다. scratch-vm 측 (또는 자체 fork) 에서 호환 작업을 진행할 때 참고용. + +## 1. 배경 + +기존 scratch-link 는 브라우저/Scratch 에디터 측 코드가 다음 전역 식별자를 통해 link 와 통신했다: + +- `ScratchLinkWebSocket` (전역 클래스, WebSocket 트랜스포트) +- `ScratchLinkSafariSocket` (전역 클래스, Safari WebExtension 트랜스포트) +- `Scratch` (전역 컨테이너 객체, `Scratch.BLE`, `Scratch.BT` 형태로 link 클라이언트 인스턴스 보관) +- ` - + diff --git a/playground.js b/playground.js index 1ead032e..9b396dd5 100644 --- a/playground.js +++ b/playground.js @@ -2,8 +2,8 @@ // Expected globals: // - JSONRPC // - Scratch -// - ScratchLinkWebSocket -// - ScratchLinkSafariSocket (if Safari extension is present) +// - AluxLabsLinkWebSocket +// - AluxLabsLinkSafariSocket (if Safari extension is present) /// class LogDisplay { @@ -74,20 +74,20 @@ class DidReceiveCallEvent extends Event { } } -class ScratchLinkClient extends JSONRPC { +class AluxLabsLinkClient extends JSONRPC { /** * @param {string} type */ constructor(type) { super(); - this._scratchLinkPeripheralType = type; + this._aluxLabsLinkPeripheralType = type; this._events = new EventTarget(); - const ScratchLinkSafariSocket = self.Scratch && self.Scratch.ScratchLinkSafariSocket; - const useSafariSocket = ScratchLinkSafariSocket && ScratchLinkSafariSocket.isSafariHelperCompatible(); + const AluxLabsLinkSafariSocket = self.AluxLabs && self.AluxLabs.AluxLabsLinkSafariSocket; + const useSafariSocket = AluxLabsLinkSafariSocket && AluxLabsLinkSafariSocket.isSafariHelperCompatible(); addLine(`Using ${useSafariSocket ? 'Safari WebExtension' : 'WebSocket'}`); this._socket = useSafariSocket ? - new ScratchLinkSafariSocket(type) : - new ScratchLinkWebSocket(type); + new AluxLabsLinkSafariSocket(type) : + new AluxLabsLinkWebSocket(type); addLine(`Socket created for ${type}`); this._socket.setOnClose(e => { addLine(`Socket closed: ${stringify(e)}`); @@ -106,12 +106,12 @@ class ScratchLinkClient extends JSONRPC { } /** - * @returns {Promise} + * @returns {Promise} */ open () { return new Promise(resolve => { this._socket.setOnOpen(() => { - addLine(`Socket opened for ${this._scratchLinkPeripheralType}`); + addLine(`Socket opened for ${this._aluxLabsLinkPeripheralType}`); resolve(this); }); this._socket.open(); @@ -119,7 +119,7 @@ class ScratchLinkClient extends JSONRPC { } } -class ScratchBLE extends ScratchLinkClient { +class AluxLabsBLE extends AluxLabsLinkClient { constructor() { super('BLE'); @@ -183,7 +183,7 @@ class ScratchBLE extends ScratchLinkClient { } } -class ScratchBT extends ScratchLinkClient { +class AluxLabsBT extends AluxLabsLinkClient { constructor() { super('BT'); } @@ -246,7 +246,7 @@ function attachFunctionToButton(buttonId, func) { } /** - * @param {ScratchLinkClient} session + * @param {AluxLabsLinkClient} session */ function getVersion(session) { return session.sendRemoteRequest('getVersion').then( @@ -260,7 +260,7 @@ function getVersion(session) { } /** - * @param {ScratchLinkClient} session + * @param {AluxLabsLinkClient} session */ function pingMe (session) { return session.sendRemoteRequest('pingMe').then( @@ -274,12 +274,12 @@ function pingMe (session) { } function initBLE() { - if (self.Scratch.BLE) { - self.Scratch.BLE._socket.close(); + if (self.AluxLabs.BLE) { + self.AluxLabs.BLE._socket.close(); } addLine('Connecting...'); - self.Scratch.BLE = new ScratchBLE(); - return self.Scratch.BLE.open(); + self.AluxLabs.BLE = new AluxLabsBLE(); + return self.AluxLabs.BLE.open(); } const filterInputsBLE = []; @@ -410,7 +410,7 @@ function discoverBLE() { deviceDetails.optionalServices = optionalServicesBLE.value.trim().split(/\s+/); } - return Scratch.BLE.requestDevice( + return AluxLabs.BLE.requestDevice( deviceDetails ).then( x => { @@ -424,9 +424,9 @@ function discoverBLE() { function connectBLE() { // this should really be implicit in `requestDevice` but splitting it out helps with debugging - return Scratch.BLE.sendRemoteRequest( + return AluxLabs.BLE.sendRemoteRequest( 'connect', - { peripheralId: Scratch.BLE.discoveredPeripheralId } + { peripheralId: AluxLabs.BLE.discoveredPeripheralId } ).then( x => { addLine(`connect resolved to: ${stringify(x)}`); @@ -438,7 +438,7 @@ function connectBLE() { } function getServicesBLE() { - return Scratch.BLE.sendRemoteRequest( + return AluxLabs.BLE.sendRemoteRequest( 'getServices' ).then( x => { @@ -458,7 +458,7 @@ function setServiceMicroBit() { } function readMicroBit() { - return Scratch.BLE.read(0xf005, '5261da01-fa7e-42ab-850b-7c80220097cc', true).then( + return AluxLabs.BLE.read(0xf005, '5261da01-fa7e-42ab-850b-7c80220097cc', true).then( x => { addLine(`read resolved to: ${stringify(x)}`); }, @@ -470,7 +470,7 @@ function readMicroBit() { function writeMicroBit() { const message = _encodeMessage('LINK'); - return Scratch.BLE.write(0xf005, '5261da02-fa7e-42ab-850b-7c80220097cc', message, 'base64').then( + return AluxLabs.BLE.write(0xf005, '5261da02-fa7e-42ab-850b-7c80220097cc', message, 'base64').then( x => { addLine(`write resolved to: ${stringify(x)}`); }, @@ -515,8 +515,8 @@ function _encodeMessage(message) { } attachFunctionToButton('initBLE', initBLE); -attachFunctionToButton('getVersionBLE', () => getVersion(self.Scratch.BLE)); -attachFunctionToButton('pingBLE', () => pingMe(self.Scratch.BLE)); +attachFunctionToButton('getVersionBLE', () => getVersion(self.AluxLabs.BLE)); +attachFunctionToButton('pingBLE', () => pingMe(self.AluxLabs.BLE)); attachFunctionToButton('discoverBLE', discoverBLE); attachFunctionToButton('connectBLE', connectBLE); attachFunctionToButton('getServicesBLE', getServicesBLE); @@ -534,16 +534,16 @@ attachFunctionToButton('addFilterBLE', addFilterBLE); addFilterBLE(); function initBT() { - if (self.Scratch.BT) { - self.Scratch.BT._socket.close(); + if (self.AluxLabs.BT) { + self.AluxLabs.BT._socket.close(); } addLine('Connecting...'); - self.Scratch.BT = new ScratchBT(); - return self.Scratch.BT.open(); + self.AluxLabs.BT = new AluxLabsBT(); + return self.AluxLabs.BT.open(); } function discoverBT() { - return Scratch.BT.requestDevice({ + return AluxLabs.BT.requestDevice({ majorDeviceClass: 8, minorDeviceClass: 1 }).then( @@ -557,7 +557,7 @@ function discoverBT() { } function connectBT() { - return Scratch.BT.connectDevice({ + return AluxLabs.BT.connectDevice({ peripheralId: document.getElementById('peripheralId').value, pin: "1234" }).then( @@ -574,7 +574,7 @@ function connectBT() { * @param {any} message */ function sendMessage(message) { - return Scratch.BT.sendMessage({ + return AluxLabs.BT.sendMessage({ message: document.getElementById('messageBody').value, encoding: 'base64' }).then( @@ -588,7 +588,7 @@ function sendMessage(message) { } function beep() { - return Scratch.BT.sendMessage({ + return AluxLabs.BT.sendMessage({ message: 'DwAAAIAAAJQBgQKC6AOC6AM=', encoding: 'base64' }).then( @@ -603,11 +603,11 @@ function beep() { const closeButton = document.getElementById('closeBT'); closeButton.onclick = () => { - self.Scratch.BT.dispose(); + self.AluxLabs.BT.dispose(); }; attachFunctionToButton('initBT', initBT); -attachFunctionToButton('getVersionBT', () => getVersion(self.Scratch.BT)); +attachFunctionToButton('getVersionBT', () => getVersion(self.AluxLabs.BT)); attachFunctionToButton('discoverBT', discoverBT); attachFunctionToButton('connectBT', connectBT); attachFunctionToButton('send', sendMessage); diff --git a/scratch-link-win-msix/Images/LockScreenLogo.scale-200.png b/scratch-link-win-msix/Images/LockScreenLogo.scale-200.png deleted file mode 100644 index ff37a993..00000000 Binary files a/scratch-link-win-msix/Images/LockScreenLogo.scale-200.png and /dev/null differ diff --git a/scratch-link-win-msix/Images/SplashScreen.scale-200.png b/scratch-link-win-msix/Images/SplashScreen.scale-200.png deleted file mode 100644 index afc0fdd2..00000000 Binary files a/scratch-link-win-msix/Images/SplashScreen.scale-200.png and /dev/null differ diff --git a/scratch-link-win-msix/Images/Square150x150Logo.scale-200.png b/scratch-link-win-msix/Images/Square150x150Logo.scale-200.png deleted file mode 100644 index 5f8efebb..00000000 Binary files a/scratch-link-win-msix/Images/Square150x150Logo.scale-200.png and /dev/null differ diff --git a/scratch-link-win-msix/Images/Square44x44Logo.scale-200.png b/scratch-link-win-msix/Images/Square44x44Logo.scale-200.png deleted file mode 100644 index 777e7e6d..00000000 Binary files a/scratch-link-win-msix/Images/Square44x44Logo.scale-200.png and /dev/null differ diff --git a/scratch-link-win-msix/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/scratch-link-win-msix/Images/Square44x44Logo.targetsize-24_altform-unplated.png deleted file mode 100644 index 93133511..00000000 Binary files a/scratch-link-win-msix/Images/Square44x44Logo.targetsize-24_altform-unplated.png and /dev/null differ diff --git a/scratch-link-win-msix/Images/StoreLogo.png b/scratch-link-win-msix/Images/StoreLogo.png deleted file mode 100644 index d14b2627..00000000 Binary files a/scratch-link-win-msix/Images/StoreLogo.png and /dev/null differ diff --git a/scratch-link-win-msix/Images/Wide310x150Logo.scale-200.png b/scratch-link-win-msix/Images/Wide310x150Logo.scale-200.png deleted file mode 100644 index 1530f6bd..00000000 Binary files a/scratch-link-win-msix/Images/Wide310x150Logo.scale-200.png and /dev/null differ diff --git a/scratch-link-win/scratch-link-tray.ico b/scratch-link-win/scratch-link-tray.ico deleted file mode 100644 index b53e3878..00000000 Binary files a/scratch-link-win/scratch-link-tray.ico and /dev/null differ diff --git a/scratch-link-win/scratch-link-win.csproj b/scratch-link-win/scratch-link-win.csproj deleted file mode 100644 index df4ac45a..00000000 --- a/scratch-link-win/scratch-link-win.csproj +++ /dev/null @@ -1,45 +0,0 @@ - - - WinExe - net6.0-windows10.0.22621.0 - win10-x86;win10-x64;win10-arm64 - 10.0.17763.0 - ScratchLink.Win - Scratch Link - Scratch Foundation - $(Company) - disable - true - None - false - enable - app.manifest - AnyCPU - scratch-link.ico - - - - - - - - - - $(ScratchVersionQuad) - $(ScratchVersionDetail) - - - - - - - - - - - - - - - - diff --git a/scratch-link-win/scratch-link.ico b/scratch-link-win/scratch-link.ico deleted file mode 100644 index 42da3ace..00000000 Binary files a/scratch-link-win/scratch-link.ico and /dev/null differ diff --git a/scripts/aws/README.md b/scripts/aws/README.md new file mode 100644 index 00000000..059140b3 --- /dev/null +++ b/scripts/aws/README.md @@ -0,0 +1,96 @@ +# Scratch Link CDN AWS Setup + +`scratch-link.aluxcoding.com` (prod) / `dev-scratch-link.aluxcoding.com` (dev) 두 환경의 S3·CloudFront·Route 53·IAM 리소스를 한 번에 프로비저닝하는 스크립트. + +설계 문서: [`docs/superpowers/specs/2026-05-26-cicd-s3-cloudfront-design.md`](../../docs/superpowers/specs/2026-05-26-cicd-s3-cloudfront-design.md) + +## 전제 + +- aws-cli v2, jq, bash 4+ (macOS는 `brew install bash`) +- AWS 관리자 권한 (IAM user/policy 생성 가능) +- Account `593793057142`, region `ap-northeast-2` +- ACM `*.aluxcoding.com` 인증서가 us-east-1에 존재 (이미 발급되어 있음) +- Route 53 `aluxcoding.com.` zone (이미 있음) + +## 실행 + +```bash +cd +./scripts/aws/setup-cdn.sh +``` + +스크립트가 AWS 호출자(account, user)를 보여주고 진행 여부를 물어봅니다. 잘못된 계정이면 `n`을 입력해 취소. + +## 산출 + +마지막에 출력되는 5개 값을 **Repository Secrets** (org가 아닌 본 repo 한정)에 등록: + +| Secret 이름 | 출처 | +|---|---| +| `AWS_REGION` | 고정 `ap-northeast-2` | +| `AWS_ACCESS_KEY_ID` | 스크립트 출력 | +| `AWS_SECRET_ACCESS_KEY` | 스크립트 출력 (1회만 보임) | +| `CF_DIST_ID_PROD` | 스크립트 출력 | +| `CF_DIST_ID_DEV` | 스크립트 출력 | + +> **왜 repo 시크릿?** `aluxrobot/scratch-link`은 `scratchfoundation/scratch-link`의 **public fork**라 org 시크릿(visibility=Private repositories)이 닿지 못한다. 본 작업의 IAM user `gh-actions-scratch-link`도 이 repo 전용이라 시크릿도 같은 스코프에 두는 게 일관적. + +### 등록 방법 두 가지 + +**(권장) gh CLI** — 값이 셸 히스토리에 안 남게: +```bash +gh secret set AWS_REGION --repo aluxrobot/scratch-link --body "ap-northeast-2" +gh secret set CF_DIST_ID_PROD --repo aluxrobot/scratch-link --body "" +gh secret set CF_DIST_ID_DEV --repo aluxrobot/scratch-link --body "" +gh secret set AWS_ACCESS_KEY_ID --repo aluxrobot/scratch-link # 프롬프트 +gh secret set AWS_SECRET_ACCESS_KEY --repo aluxrobot/scratch-link # 프롬프트 +``` + +**브라우저**: https://github.com/aluxrobot/scratch-link/settings/secrets/actions → "New repository secret". + +## 멱등성 + +- 모든 리소스는 존재 확인 후 skip +- IAM 정책은 항상 덮어쓰기 (안전) +- IAM access key는 이미 있으면 skip (secret 재조회 불가). 강제 신규 발급: `FORCE_NEW_KEY=1 ./scripts/aws/setup-cdn.sh` + +## CloudFront 전파 대기 + +생성 직후 `In-Progress` 상태. Deployed 될 때까지 5~15분. + +```bash +aws cloudfront get-distribution --id $CF_DIST_ID_PROD --query 'Distribution.Status' +``` + +`Deployed`가 뜨면 https://scratch-link.aluxcoding.com/ 접근 가능 (단, DNS 전파도 같이 필요. 보통 즉시 ~ 수 분). + +## 롤백·재구성 + +생성된 리소스를 일괄 제거하는 스크립트는 만들지 않음. 필요 시: + +```bash +# CloudFront disable + delete +aws cloudfront update-distribution --id --if-match --distribution-config +aws cloudfront delete-distribution --id --if-match + +# Route 53 레코드 삭제 +aws route53 change-resource-record-sets --hosted-zone-id Z0327990CY2GCD1RONPB --change-batch + +# S3 버킷 비우고 삭제 +aws s3 rm s3://scratch-link.aluxcoding.com --recursive +aws s3api delete-bucket --bucket scratch-link.aluxcoding.com + +# IAM user +aws iam delete-user-policy --user-name gh-actions-scratch-link --policy-name scratch-link-cdn-deploy +aws iam delete-access-key --user-name gh-actions-scratch-link --access-key-id +aws iam delete-user --user-name gh-actions-scratch-link +``` + +## 트러블슈팅 + +| 증상 | 원인 / 조치 | +|---|---| +| `BucketAlreadyOwnedByYou` 외의 `BucketAlreadyExists` | 글로벌하게 같은 이름의 버킷이 다른 계정에서 사용 중. 도메인 이름을 바꿔야 함. | +| CloudFront 생성 시 `CNAMEAlreadyExists` | 다른 distribution이 같은 alias를 들고 있음. 기존 distribution을 disable/delete 또는 alias 회수 필요. | +| `InvalidViewerCertificate` | ACM 인증서가 us-east-1이 아니거나 ISSUED 상태가 아님. `ACM_CERT_ARN` 재확인. | +| `MalformedPolicyDocument` | IAM 정책 템플릿의 placeholder 미치환. `setup-cdn.sh`가 sed 치환을 정상 수행했는지 stderr 로그 확인. | diff --git a/scripts/aws/lib/bucket.sh b/scripts/aws/lib/bucket.sh new file mode 100644 index 00000000..8e8dd4a9 --- /dev/null +++ b/scripts/aws/lib/bucket.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# S3 버킷 생성·구성 함수. setup-cdn.sh에서 source. + +# 인자: $1 = 버킷명 +ensure_bucket() { + local bucket="$1" + local region="$AWS_REGION" + + if aws s3api head-bucket --bucket "$bucket" 2>/dev/null; then + log_info "버킷 이미 존재: $bucket — 생성 skip" + else + log_info "버킷 생성: $bucket (region=$region)" + aws s3api create-bucket \ + --bucket "$bucket" \ + --region "$region" \ + --create-bucket-configuration "LocationConstraint=$region" \ + >/dev/null + log_ok "버킷 생성됨: $bucket" + fi + + log_info "Public Access Block 해제: $bucket" + aws s3api put-public-access-block \ + --bucket "$bucket" \ + --public-access-block-configuration \ + "BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false" + + log_info "Public-read 정책 적용: $bucket" + local policy_json + policy_json=$(sed "s/__BUCKET__/$bucket/g" "$(dirname "${BASH_SOURCE[0]}")/../policies/bucket-policy.json.tpl") + aws s3api put-bucket-policy --bucket "$bucket" --policy "$policy_json" + + log_info "Website hosting 활성화: $bucket" + aws s3 website "s3://$bucket/" --index-document index.html --error-document error.html + # MSIX 다운로드 용도라 index/error 페이지는 실제로 안 쓰이지만, website endpoint 활성화에 필수. + + log_ok "버킷 구성 완료: $bucket" +} diff --git a/scripts/aws/lib/cloudfront.sh b/scripts/aws/lib/cloudfront.sh new file mode 100644 index 00000000..5ea19522 --- /dev/null +++ b/scripts/aws/lib/cloudfront.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# CloudFront distribution 생성. setup-cdn.sh에서 source. + +# 인자: $1 = 도메인 (== alias, == 버킷명) +# $2 = comment (UI에서 식별용) +# 출력: stdout 한 줄. "DIST_ID\tCF_DOMAIN" (tab 구분) +ensure_distribution() { + local domain="$1" + local comment="$2" + local origin_domain="${domain}.s3-website.${AWS_REGION}.amazonaws.com" + + local existing + # `|| \`[]\``: alias 없는 다른 distribution의 null Items에서 contains() 에러를 회피. + existing=$(aws cloudfront list-distributions \ + --query "DistributionList.Items[?contains(Aliases.Items || \`[]\`, \`$domain\`)].{Id:Id,Domain:DomainName}" \ + --output json) + + local count + count=$(jq 'length' <<<"$existing") + + if [[ "$count" -ge 1 ]]; then + local dist_id dist_domain + dist_id=$(jq -r '.[0].Id' <<<"$existing") + dist_domain=$(jq -r '.[0].Domain' <<<"$existing") + log_info "CloudFront 이미 존재 ($domain): $dist_id" >&2 + printf "%s\t%s\n" "$dist_id" "$dist_domain" + return 0 + fi + + log_info "CloudFront distribution 생성: $domain" + local tpl="$(dirname "${BASH_SOURCE[0]}")/../policies/cloudfront-config.json.tpl" + local caller_ref + caller_ref="scratch-link-$(date +%s)-$$" + + local config_json + config_json=$(sed \ + -e "s/__CALLER_REF__/$caller_ref/g" \ + -e "s|__COMMENT__|$comment|g" \ + -e "s/__DOMAIN__/$domain/g" \ + -e "s/__ORIGIN_DOMAIN__/$origin_domain/g" \ + -e "s|__CERT_ARN__|$ACM_CERT_ARN|g" \ + "$tpl") + + local result + result=$(aws cloudfront create-distribution \ + --distribution-config "$config_json" \ + --output json) + + local dist_id dist_domain + dist_id=$(jq -r '.Distribution.Id' <<<"$result") + dist_domain=$(jq -r '.Distribution.DomainName' <<<"$result") + + log_ok "CloudFront 생성됨 ($domain): $dist_id / $dist_domain" >&2 + log_warn "Distribution 배포(In-Progress → Deployed)에는 5~15분 소요." >&2 + + printf "%s\t%s\n" "$dist_id" "$dist_domain" +} diff --git a/scripts/aws/lib/common.sh b/scripts/aws/lib/common.sh new file mode 100755 index 00000000..af50b29d --- /dev/null +++ b/scripts/aws/lib/common.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# 공통 유틸: 로깅, 환경 변수, 사전 점검. +# 호출 측에서 `source "$(dirname "$0")/lib/common.sh"`로 사용. + +# bash 4+ 필요 (associative array 등) +if (( BASH_VERSINFO[0] < 4 )); then + echo "ERROR: bash 4 이상 필요 (현재: $BASH_VERSION). macOS는 'brew install bash' 후 /opt/homebrew/bin/bash로 실행." >&2 + exit 1 +fi + +set -euo pipefail + +# 색상 로그 +RED=$'\033[31m'; GREEN=$'\033[32m'; YELLOW=$'\033[33m'; BLUE=$'\033[34m'; RESET=$'\033[0m' +log_info() { printf "%s[INFO]%s %s\n" "$BLUE" "$RESET" "$*" >&2; } +log_warn() { printf "%s[WARN]%s %s\n" "$YELLOW" "$RESET" "$*" >&2; } +log_error() { printf "%s[ERROR]%s %s\n" "$RED" "$RESET" "$*" >&2; } +log_ok() { printf "%s[OK]%s %s\n" "$GREEN" "$RESET" "$*" >&2; } + +# 필수 외부 명령 점검 +require_cmd() { + local missing=() + for cmd in "$@"; do + if ! command -v "$cmd" >/dev/null 2>&1; then + missing+=("$cmd") + fi + done + if (( ${#missing[@]} > 0 )); then + log_error "다음 명령이 없습니다: ${missing[*]}" + exit 1 + fi +} + +# AWS 호출자 식별 출력 (실수 방지) +print_aws_identity() { + local id_json + id_json=$(aws sts get-caller-identity) + local account user + account=$(jq -r '.Account' <<<"$id_json") + user=$(jq -r '.Arn' <<<"$id_json") + log_info "AWS Account: $account" + log_info "Caller: $user" +} + +# 환경(prod/dev) → 도메인·버킷명 매핑 +domain_for_env() { + case "$1" in + prod) echo "scratch-link.aluxcoding.com" ;; + dev) echo "dev-scratch-link.aluxcoding.com" ;; + *) log_error "알 수 없는 환경: $1"; return 1 ;; + esac +} + +# 공용 상수 +export AWS_REGION="${AWS_REGION:-ap-northeast-2}" +export ACM_CERT_ARN="${ACM_CERT_ARN:-arn:aws:acm:us-east-1:593793057142:certificate/0b58642f-b20f-451b-8257-aa366ba5fc0c}" +export ROUTE53_ZONE_ID="${ROUTE53_ZONE_ID:-Z0327990CY2GCD1RONPB}" +export IAM_USER_NAME="${IAM_USER_NAME:-gh-actions-scratch-link}" diff --git a/scripts/aws/lib/iam.sh b/scripts/aws/lib/iam.sh new file mode 100644 index 00000000..c91a1f06 --- /dev/null +++ b/scripts/aws/lib/iam.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# IAM user·policy·access key 함수. setup-cdn.sh에서 source. + +# IAM user 생성 (멱등). 출력 없음. +ensure_iam_user() { + if aws iam get-user --user-name "$IAM_USER_NAME" >/dev/null 2>&1; then + log_info "IAM user 이미 존재: $IAM_USER_NAME — skip" + return 0 + fi + log_info "IAM user 생성: $IAM_USER_NAME" + aws iam create-user --user-name "$IAM_USER_NAME" >/dev/null + log_ok "IAM user 생성됨: $IAM_USER_NAME" +} + +# 인라인 정책 attach (idempotent — put-user-policy는 덮어쓰기). +# 인자: $1 = AWS Account ID, $2 = PROD_DIST_ID, $3 = DEV_DIST_ID +attach_iam_policy() { + local account="$1" + local prod_id="$2" + local dev_id="$3" + local tpl="$(dirname "${BASH_SOURCE[0]}")/../policies/iam-policy.json.tpl" + + log_info "IAM 인라인 정책 attach (gh-actions-scratch-link 정책)" + local policy_json + policy_json=$(sed \ + -e "s/__ACCOUNT__/$account/g" \ + -e "s/__PROD_DIST_ID__/$prod_id/g" \ + -e "s/__DEV_DIST_ID__/$dev_id/g" \ + "$tpl") + + aws iam put-user-policy \ + --user-name "$IAM_USER_NAME" \ + --policy-name "scratch-link-cdn-deploy" \ + --policy-document "$policy_json" + log_ok "IAM 정책 attach 완료" +} + +# access key 발급 또는 기존 키 안내. +# 기존 키가 있으면 secret을 다시 볼 수 없으므로, 사용자에게 옵션을 묻는다. +# 출력: stdout 한 줄. "ACCESS_KEY_ID\tSECRET_ACCESS_KEY" (신규 발급 시) 또는 빈 줄 (skip). +ensure_access_key() { + local existing + existing=$(aws iam list-access-keys --user-name "$IAM_USER_NAME" \ + --query 'AccessKeyMetadata[].AccessKeyId' --output json) + local count + count=$(jq 'length' <<<"$existing") + + if [[ "$count" -ge 1 ]]; then + log_warn "IAM user에 access key가 이미 ${count}개 있음: $(jq -r 'join(", ")' <<<"$existing")" + log_warn "기존 키의 secret은 재조회 불가. 분실 시 'aws iam delete-access-key' 후 재실행." + log_warn "신규 키 발급 원하면 환경변수 FORCE_NEW_KEY=1로 재실행 (단, IAM 한도 2개)." + if [[ "${FORCE_NEW_KEY:-}" != "1" ]]; then + printf "\n" + return 0 + fi + fi + + log_info "access key 발급: $IAM_USER_NAME" + local result + result=$(aws iam create-access-key --user-name "$IAM_USER_NAME" --output json) + local key_id secret + key_id=$(jq -r '.AccessKey.AccessKeyId' <<<"$result") + secret=$(jq -r '.AccessKey.SecretAccessKey' <<<"$result") + log_ok "신규 access key 발급됨: $key_id" + printf "%s\t%s\n" "$key_id" "$secret" +} diff --git a/scripts/aws/lib/route53.sh b/scripts/aws/lib/route53.sh new file mode 100644 index 00000000..ca4890e9 --- /dev/null +++ b/scripts/aws/lib/route53.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# Route 53 A/AAAA alias 생성. setup-cdn.sh에서 source. + +# 인자: $1 = 도메인 (예: scratch-link.aluxcoding.com) +# $2 = CloudFront 도메인 (예: d123abc.cloudfront.net) +ensure_route53_alias() { + local domain="$1" + local cf_domain="$2" + # CloudFront는 hosted zone ID가 전 리전 동일: Z2FDTNDATAQYW2 + local cf_zone="Z2FDTNDATAQYW2" + + # 기존 레코드 확인 + local existing + existing=$(aws route53 list-resource-record-sets \ + --hosted-zone-id "$ROUTE53_ZONE_ID" \ + --query "ResourceRecordSets[?Name=='${domain}.' && (Type=='A' || Type=='AAAA')]" \ + --output json) + + local existing_count + existing_count=$(jq 'length' <<<"$existing") + + if [[ "$existing_count" -ge 2 ]]; then + # A + AAAA 둘 다 있고, target이 일치하면 skip + local existing_target + existing_target=$(jq -r '.[0].AliasTarget.DNSName // ""' <<<"$existing") + if [[ "$existing_target" == "${cf_domain}." ]]; then + log_info "Route 53 alias 이미 존재 ($domain → $cf_domain) — skip" + return 0 + fi + log_warn "Route 53 alias가 다른 타겟을 가리키고 있음 ($existing_target). 덮어쓰기 진행." + fi + + log_info "Route 53 A/AAAA alias 추가: $domain → $cf_domain" + + local change_batch + change_batch=$(cat </dev/null + + log_ok "Route 53 alias 등록됨 ($domain)" +} diff --git a/scripts/aws/policies/bucket-policy.json.tpl b/scripts/aws/policies/bucket-policy.json.tpl new file mode 100644 index 00000000..75aebe70 --- /dev/null +++ b/scripts/aws/policies/bucket-policy.json.tpl @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "PublicReadGetObject", + "Effect": "Allow", + "Principal": "*", + "Action": "s3:GetObject", + "Resource": "arn:aws:s3:::__BUCKET__/*" + } + ] +} diff --git a/scripts/aws/policies/cloudfront-config.json.tpl b/scripts/aws/policies/cloudfront-config.json.tpl new file mode 100644 index 00000000..d33d6590 --- /dev/null +++ b/scripts/aws/policies/cloudfront-config.json.tpl @@ -0,0 +1,48 @@ +{ + "CallerReference": "__CALLER_REF__", + "Comment": "__COMMENT__", + "Aliases": { + "Quantity": 1, + "Items": ["__DOMAIN__"] + }, + "DefaultRootObject": "", + "Origins": { + "Quantity": 1, + "Items": [ + { + "Id": "s3-website-origin", + "DomainName": "__ORIGIN_DOMAIN__", + "CustomOriginConfig": { + "HTTPPort": 80, + "HTTPSPort": 443, + "OriginProtocolPolicy": "http-only", + "OriginSslProtocols": { "Quantity": 1, "Items": ["TLSv1.2"] }, + "OriginReadTimeout": 30, + "OriginKeepaliveTimeout": 5 + }, + "ConnectionAttempts": 3, + "ConnectionTimeout": 10 + } + ] + }, + "DefaultCacheBehavior": { + "TargetOriginId": "s3-website-origin", + "ViewerProtocolPolicy": "redirect-to-https", + "AllowedMethods": { + "Quantity": 2, + "Items": ["GET", "HEAD"], + "CachedMethods": { "Quantity": 2, "Items": ["GET", "HEAD"] } + }, + "Compress": true, + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6" + }, + "PriceClass": "PriceClass_200", + "Enabled": true, + "ViewerCertificate": { + "ACMCertificateArn": "__CERT_ARN__", + "SSLSupportMethod": "sni-only", + "MinimumProtocolVersion": "TLSv1.2_2021" + }, + "HttpVersion": "http2and3", + "IsIPV6Enabled": true +} diff --git a/scripts/aws/policies/iam-policy.json.tpl b/scripts/aws/policies/iam-policy.json.tpl new file mode 100644 index 00000000..de2d0c85 --- /dev/null +++ b/scripts/aws/policies/iam-policy.json.tpl @@ -0,0 +1,25 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "S3Upload", + "Effect": "Allow", + "Action": ["s3:PutObject", "s3:DeleteObject", "s3:ListBucket"], + "Resource": [ + "arn:aws:s3:::scratch-link.aluxcoding.com", + "arn:aws:s3:::scratch-link.aluxcoding.com/*", + "arn:aws:s3:::dev-scratch-link.aluxcoding.com", + "arn:aws:s3:::dev-scratch-link.aluxcoding.com/*" + ] + }, + { + "Sid": "CloudFrontInvalidate", + "Effect": "Allow", + "Action": ["cloudfront:CreateInvalidation", "cloudfront:GetInvalidation"], + "Resource": [ + "arn:aws:cloudfront::__ACCOUNT__:distribution/__PROD_DIST_ID__", + "arn:aws:cloudfront::__ACCOUNT__:distribution/__DEV_DIST_ID__" + ] + } + ] +} diff --git a/scripts/aws/setup-cdn.sh b/scripts/aws/setup-cdn.sh new file mode 100755 index 00000000..13652802 --- /dev/null +++ b/scripts/aws/setup-cdn.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +# Scratch Link CDN AWS 인프라 일회성 셋업. +# 멱등: 다시 실행해도 안전. 자세한 절차는 scripts/aws/README.md 참고. + +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# shellcheck source=lib/common.sh +source "$SCRIPT_DIR/lib/common.sh" +# shellcheck source=lib/bucket.sh +source "$SCRIPT_DIR/lib/bucket.sh" +# shellcheck source=lib/cloudfront.sh +source "$SCRIPT_DIR/lib/cloudfront.sh" +# shellcheck source=lib/route53.sh +source "$SCRIPT_DIR/lib/route53.sh" +# shellcheck source=lib/iam.sh +source "$SCRIPT_DIR/lib/iam.sh" + +require_cmd aws jq sed +print_aws_identity + +read -r -p "위 계정·사용자로 진행할까요? (y/N) " confirm +if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then + log_info "취소" + exit 0 +fi + +# 1. S3 버킷 +for env in prod dev; do + domain=$(domain_for_env "$env") + ensure_bucket "$domain" +done + +# 2. CloudFront distribution +declare -A DIST_ID DIST_DOMAIN +for env in prod dev; do + domain=$(domain_for_env "$env") + comment="scratch-link CDN ($env)" + result=$(ensure_distribution "$domain" "$comment") + DIST_ID[$env]=$(cut -f1 <<<"$result") + DIST_DOMAIN[$env]=$(cut -f2 <<<"$result") +done + +# 3. Route 53 alias +for env in prod dev; do + domain=$(domain_for_env "$env") + ensure_route53_alias "$domain" "${DIST_DOMAIN[$env]}" +done + +# 4. IAM user +ensure_iam_user +ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +attach_iam_policy "$ACCOUNT_ID" "${DIST_ID[prod]}" "${DIST_ID[dev]}" + +# 5. access key +key_line=$(ensure_access_key) + +# 6. 요약 출력 (사용자가 GitHub Secret으로 옮길 정보) +cat >&2 <&2 <&2 <&2 <