From b449db2fca5c345db719c7ff827e61af669f6e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Sch=C3=A4rer?= <143824611+marc-n-dream@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:58:35 +0200 Subject: [PATCH 1/4] ci: add fail-closed proprietary-source guard Block native (Java/Kotlin) source, the private Gradle build system, and the private build pipeline from this public repo. Native code ships only as compiled .aar/.unitypackage/.bundle artifacts; the source lives in the private airconsole-unity-android-plugin and airconsole-unity-webview repos. Denylist (scripts/check-proprietary-source.sh, bash 3.2 safe): - *.java/*.kt/*.kts, *.gradle, *.pro, gradle wrapper/properties - *.sh/Rakefile/*.rake build scripts, *.toml version catalogs - AndroidManifest.xml, src/main/res/, .gitmodules - source patterns also match backup/merge suffixes (.orig/.bak/~/.txt) Allowlist: Unity gradle templates, this script, content-free *.meta. Layers: - .githooks/pre-commit: fast local gate (git config core.hooksPath .githooks) - .github/workflows/no-proprietary-source.yml: authoritative CI gate on every push (any branch) and PR, plus a submodule-gitlink rejection - .gitignore: ignore *.orig/*.bak/*~ so leaked source is not staged at all - AGENTS.md: contributor rules + hook install Denylist and layering verified against an adversarial red-team of the two private repos' full file inventory (10 confirmed gaps closed). Co-Authored-By: Claude Opus 4.8 --- .githooks/pre-commit | 27 ++++ .github/workflows/no-proprietary-source.yml | 37 +++++ .gitignore | 10 ++ AGENTS.md | 9 ++ scripts/check-proprietary-source.sh | 149 ++++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100755 .githooks/pre-commit create mode 100644 .github/workflows/no-proprietary-source.yml create mode 100755 scripts/check-proprietary-source.sh diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 00000000..a87a81fb --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# +# pre-commit: block proprietary source from entering this public repo. +# Enable with: git config core.hooksPath .githooks +# +# Checks only the staged (added/copied/modified) files for speed. +# POSIX bash 3.2 compatible (stock macOS). +set -euo pipefail + +repo_root="$(git rev-parse --show-toplevel)" +checker="$repo_root/scripts/check-proprietary-source.sh" + +if [ ! -x "$checker" ]; then + echo "pre-commit: $checker missing or not executable; skipping guard." >&2 + exit 0 +fi + +staged=() +while IFS= read -r f; do + [ -n "$f" ] && staged+=("$f") +done < <(git diff --cached --name-only --diff-filter=ACM) + +if [ "${#staged[@]}" -eq 0 ]; then + exit 0 +fi + +"$checker" "${staged[@]}" diff --git a/.github/workflows/no-proprietary-source.yml b/.github/workflows/no-proprietary-source.yml new file mode 100644 index 00000000..847ea8db --- /dev/null +++ b/.github/workflows/no-proprietary-source.yml @@ -0,0 +1,37 @@ +name: No proprietary source + +# Fail-closed gate: keeps native (Java/Kotlin) source, the private Gradle +# build system, and the private build pipeline out of this public repo. +# Native code ships only as compiled .aar / .unitypackage / .bundle artifacts. +# See scripts/check-proprietary-source.sh for the denylist and rationale. +# +# Runs on every push to ANY branch (the repo is public, so a pushed branch is +# world-visible even without a PR) and on every PR. + +on: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: ['**'] + +jobs: + no-proprietary-source: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Scan tracked files for proprietary source + run: bash scripts/check-proprietary-source.sh + shell: bash + + - name: Reject submodule gitlinks + run: | + gitlinks=$(git ls-files -s | awk '$1 == "160000" { print $4 }') + if [ -n "$gitlinks" ]; then + echo "ERROR: submodule gitlink(s) found — the private repos must not be" >&2 + echo "referenced as submodules in this public repo:" >&2 + echo "$gitlinks" | sed 's/^/ - /' >&2 + exit 1 + fi + shell: bash diff --git a/.gitignore b/.gitignore index 1319889e..a5c671ec 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,16 @@ obj/ ehthumbs.db Thumbs.db +# ============ # +# Backup / merge artifacts (defense-in-depth: keep proprietary source that +# leaks into *.orig/*.bak/*~ from being staged by `git add -A`). The guard +# in scripts/check-proprietary-source.sh is the enforced backstop. +# ============ # +*.orig +*.rej +*.bak +*~ + # ============ # # Visual Studio Code generated # # ============ # diff --git a/AGENTS.md b/AGENTS.md index 60b19f01..575889c4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -93,6 +93,15 @@ Unity build: run from Unity Editor or configured Unity batchmode build. PostprocessBuild auto runs during Unity build. Export package: use Unity export package workflow for `.unitypackage`. Run tests: use Unity Test Runner for EditMode and PlayMode suites. +## PROPRIETARY-SOURCE GUARD +This repo is PUBLIC. Native Android and webview source is PRIVATE and ships here only as compiled artifacts. +NEVER commit native source or the private build system: `*.java`, `*.kt`, Gradle files, `*.sh`/`Rakefile`/`*.rake` build scripts, `*.toml` version catalogs, `AndroidManifest.xml`, `src/main/res/`. +Only compiled artifacts (`.aar`, `.unitypackage`, `.bundle`) and glue (`.cs`, `.jslib`, `.mm`) belong here. +`scripts/check-proprietary-source.sh` is the shared denylist check. +CI `.github/workflows/no-proprietary-source.yml` is the authoritative gate; it scans every push (any branch) and PR. +Enable the fast local pre-commit guard once per clone: `git config core.hooksPath .githooks`. +A path guard cannot see file contents: never paste native source into an accepted file (`.cs`, `.md`) either. + ## FORBIDDEN NEVER hardcode device IDs. NO platform specific code outside `plugins/`. diff --git a/scripts/check-proprietary-source.sh b/scripts/check-proprietary-source.sh new file mode 100755 index 00000000..4622d987 --- /dev/null +++ b/scripts/check-proprietary-source.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +# +# check-proprietary-source.sh +# +# Fail-closed guard that keeps AirConsole proprietary source out of this +# PUBLIC (open-source) repository. +# +# The native Android library (airconsole-unity-android-plugin) and the +# native webview build inputs (airconsole-unity-webview) are maintained in +# separate PRIVATE repositories. Only their COMPILED artifacts are allowed +# to ship here: +# +# - unityandroidlibrary.aar (Android native, compiled) +# - WebViewPlugin-*.aar.tmpl (webview native, compiled) +# - *.unitypackage / *.bundle (compiled) +# +# Source languages (*.java, *.kt), the Gradle build system, and the private +# build pipeline (shell/Rake scripts, version catalogs) reveal the internal +# technology and MUST NOT be committed here. A leak is effectively +# irreversible once pushed (git history, forks, indexers), so this check +# blocks by default and only whitelists Unity's own boilerplate + the +# content-free files listed below. +# +# Each source pattern also matches a trailing backup/merge/rename suffix +# (e.g. Foo.java.orig, build.gradle.bak, Plugin.kt~, Foo.java.txt) because +# git merge/rebase (.orig/.rej) and editors (~/.bak) create sibling files +# that hold the full verbatim source. +# +# KNOWN LIMITATIONS (a path denylist cannot see file CONTENT): +# - Proprietary source hand-pasted into an accepted file (.md/.cs) is not +# detected. Deliberately renaming source to an accepted extension is not +# detected. Both are outside the ACCIDENTAL-leak threat model this guard +# targets (git add -A after copying a native dir keeps real extensions, +# which ARE blocked). If the native stack ever gains C/C++/NDK sources +# (*.c/*.cpp/*.h/*.aidl) or loose native libs, add them below. +# +# Usage: +# check-proprietary-source.sh [file ...] +# - with file arguments: checks exactly those paths (pre-commit hook) +# - with no arguments: checks every tracked file (CI full-tree scan) +# +# Exit status: 0 = clean, 1 = proprietary source found. +# +# POSIX bash 3.2 compatible (stock macOS) — no mapfile / associative arrays. + +set -euo pipefail + +# Suffix that may trail a source extension: end-of-path, or a '.' / '~' that +# begins a backup/merge/rename tail (.orig .bak .rej .txt .BACKUP.N, ~). +S='($|[.~])' + +# --- Denylist (parallel arrays; matched case-insensitively on the path) ------ +DENY_PATTERN=( + "\.(java|kt|kts)$S" + "\.gradle$S" + "\.pro$S" + "\.sh$S" + "\.toml$S" + "\.rake$S" + "(^|/)gradlew(\.bat)?$S" + "(^|/)gradle/wrapper/" + "(^|/)gradle\.properties$S" + "(^|/)Rakefile$S" + "(^|/)\.gitmodules$S" + "(^|/)AndroidManifest\.xml$S" + "(^|/)src/main/res/" +) +DENY_REASON=( + 'native source (Java/Kotlin) — ships as a compiled .aar, never as source' + 'Gradle build script — reveals the private build setup' + 'ProGuard rules — reveal internal class structure' + 'shell build/install script — reveals the private build pipeline' + 'version catalog (.toml) — reveals the private dependency stack' + 'Rake build task — reveals the private build pipeline' + 'Gradle wrapper' + 'Gradle wrapper' + 'Gradle properties' + 'Ruby packaging build script — reveals the private build pipeline' + 'submodule reference — would disclose a private repository URL' + 'native Android manifest — declares internal components/permissions' + 'native Android resources — belong to the private library' +) + +# --- Allowlist: the ONLY exceptions to the denylist above -------------------- +# 1. Unity's own Android build templates (public boilerplate). +# 2. This guard script itself (the repo's own tooling). +# 3. *.meta — Unity import sidecars are content-free (GUID + import settings); +# they never contain source, so a Foo.java.meta / mainTemplate.gradle.meta +# is safe even though its base name trips a deny pattern. +ALLOW_PATTERN='(^|/)(mainTemplate|launcherTemplate|baseProjectTemplate|settingsTemplate)\.gradle$|(^|/)gradleTemplate\.properties$|(^|/)scripts/check-proprietary-source\.sh$|\.meta$' + +# --- Combined deny regex for one fast first-pass grep ------------------------ +combined="" +for p in "${DENY_PATTERN[@]}"; do + if [ -n "$combined" ]; then + combined="$combined|($p)" + else + combined="($p)" + fi +done + +# --- Emit the list of files to check ----------------------------------------- +list_files() { + if [ "$#" -gt 0 ]; then + printf '%s\n' "$@" + else + # No args → scan the whole tracked tree (CI standing invariant). + git ls-files + fi +} + +# --- reason_for : echo the denylist reason that matched ---------------- +reason_for() { + local path="$1" i + for i in "${!DENY_PATTERN[@]}"; do + if printf '%s' "$path" | grep -Eiq -- "${DENY_PATTERN[$i]}"; then + printf '%s' "${DENY_REASON[$i]}" + return + fi + done + printf '%s' 'proprietary source' +} + +violations=0 +while IFS= read -r path; do + [ -n "$path" ] || continue + # Skip explicitly allowlisted files. + if printf '%s' "$path" | grep -Eiq -- "$ALLOW_PATTERN"; then + continue + fi + if [ "$violations" -eq 0 ]; then + echo "ERROR: proprietary source must not be committed to this public repository." >&2 + echo >&2 + fi + printf ' \xe2\x9c\x97 %s\n -> %s\n' "$path" "$(reason_for "$path")" >&2 + violations=$((violations + 1)) +done < <(list_files "$@" | grep -Ei -- "$combined" || true) + +if [ "$violations" -gt 0 ]; then + echo >&2 + echo "Found $violations blocked file(s)." >&2 + echo "Native code lives in the private repos and ships here only as compiled" >&2 + echo "artifacts (.aar / .unitypackage / .bundle). Remove the source file(s) above." >&2 + echo "If a file is genuinely Unity boilerplate, add it to the ALLOW list in" >&2 + echo "scripts/check-proprietary-source.sh with justification." >&2 + exit 1 +fi + +exit 0 From 849c0dd0984a74d04ce4c793fe05ee83f5471bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Sch=C3=A4rer?= <143824611+marc-n-dream@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:58:35 +0200 Subject: [PATCH 2/4] ai: Remove serena cache from git --- .serena/.gitignore | 1 - .serena/memories/project_overview.md | 6 - .serena/memories/style_and_conventions.md | 4 - .serena/memories/suggested_commands.md | 6 - .serena/memories/task_completion.md | 6 - .serena/project.yml | 133 ---------------------- 6 files changed, 156 deletions(-) delete mode 100644 .serena/.gitignore delete mode 100644 .serena/memories/project_overview.md delete mode 100644 .serena/memories/style_and_conventions.md delete mode 100644 .serena/memories/suggested_commands.md delete mode 100644 .serena/memories/task_completion.md delete mode 100644 .serena/project.yml diff --git a/.serena/.gitignore b/.serena/.gitignore deleted file mode 100644 index 14d86ad6..00000000 --- a/.serena/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/cache diff --git a/.serena/memories/project_overview.md b/.serena/memories/project_overview.md deleted file mode 100644 index 411e2377..00000000 --- a/.serena/memories/project_overview.md +++ /dev/null @@ -1,6 +0,0 @@ -# Project Overview -- Purpose: Unity plugin providing a C# wrapper around the AirConsole JavaScript API so Unity developers can build local multiplayer games that communicate with the AirConsole backend through the embedded web/websocket server. -- Tech stack: Unity/C# scripts plus accompanying assets located primarily under `Assets/`. Targets AirConsole-supported platforms (WebGL and Android TV). -- Repo structure highlights: Unity project root with standard folders (`Assets`, `Packages`, `ProjectSettings`, etc.), csproj files for various Unity modules/tests, documentation PDF in `Assets/AirConsole/Documentation_1.7.pdf`, and changelog/README at root. -- Entry points: open the Unity project (`airconsole-unity-plugin.sln` or via Unity Hub) and use provided AirConsole scenes/examples under `Assets/AirConsole` as the starting point. -- Special notes: includes embedded webserver/websocket server for editor communication, so no extra server dependency is required. \ No newline at end of file diff --git a/.serena/memories/style_and_conventions.md b/.serena/memories/style_and_conventions.md deleted file mode 100644 index b79fa29b..00000000 --- a/.serena/memories/style_and_conventions.md +++ /dev/null @@ -1,4 +0,0 @@ -# Style and Conventions -- Code is written in standard Unity/C# style (PascalCase for classes/methods, camelCase for private fields, serialized fields attributed as needed). -- Project relies on Unity-specific patterns (MonoBehaviours, scriptable objects, etc.); follow Unity's serialization and inspector conventions when modifying scripts. -- No repository-specific linting or formatting rules were documented, so adhere to default C# conventions and Unity best practices. \ No newline at end of file diff --git a/.serena/memories/suggested_commands.md b/.serena/memories/suggested_commands.md deleted file mode 100644 index 015c78e8..00000000 --- a/.serena/memories/suggested_commands.md +++ /dev/null @@ -1,6 +0,0 @@ -# Suggested Commands -- `git status` / `git diff` – inspect working tree and patch content. -- `ls` / `find . -name "*.cs"` – explore repository contents on macOS (Darwin) shell. -- `open airconsole-unity-plugin.sln` or launch via Unity Hub to edit/run the Unity project. -- Use the Unity Test Runner inside the Unity Editor to execute EditMode/PlayMode tests (no standalone CLI documented). -- Refer to the embedded documentation PDF at `Assets/AirConsole/Documentation_1.7.pdf` for setup instructions. \ No newline at end of file diff --git a/.serena/memories/task_completion.md b/.serena/memories/task_completion.md deleted file mode 100644 index ccb983dd..00000000 --- a/.serena/memories/task_completion.md +++ /dev/null @@ -1,6 +0,0 @@ -# Task Completion Checklist -- Ensure changes build inside the Unity Editor and do not break the AirConsole example scenes. -- Run relevant Unity EditMode/PlayMode tests through the Unity Test Runner if scripts were modified. -- Update README/CHANGELOG or documentation PDF references if behavior changes. -- Verify WebGL/Android-specific behavior when applicable (e.g., platform messaging, webview debugging instructions). -- Commit with clear messages and keep the embedded webserver/websocket functionality intact. \ No newline at end of file diff --git a/.serena/project.yml b/.serena/project.yml deleted file mode 100644 index b58f439f..00000000 --- a/.serena/project.yml +++ /dev/null @@ -1,133 +0,0 @@ - - -# list of languages for which language servers are started; choose from: -# al angular ansible bash clojure -# cpp cpp_ccls crystal csharp csharp_omnisharp -# dart elixir elm erlang fortran -# fsharp go groovy haskell haxe -# hlsl html java json julia -# kotlin lean4 lua luau markdown -# matlab msl nix ocaml pascal -# perl php php_phpactor powershell python -# python_jedi python_ty r rego ruby -# ruby_solargraph rust scala scss solidity -# svelte swift systemverilog terraform toml -# typescript typescript_vts vue yaml zig -# (This list may be outdated. For the current list, see values of Language enum here: -# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py -# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) -# Note: -# - For C, use cpp -# - For JavaScript, use typescript -# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root) -# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm) -# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three) -# - For Free Pascal/Lazarus, use pascal -# Special requirements: -# Some languages require additional setup/installations. -# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers -# When using multiple languages, the first language server that supports a given file will be used for that file. -# The first language is the default language and the respective language server will be used as a fallback. -# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. -languages: -- csharp - -# the encoding used by text files in the project -# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings -encoding: "utf-8" - -# whether to use project's .gitignore files to ignore files -ignore_all_files_in_gitignore: true - -# list of additional paths to ignore in this project. -# Same syntax as gitignore, so you can use * and **. -# Note: global ignored_paths from serena_config.yml are also applied additively. -ignored_paths: [] - -# whether the project is in read-only mode -# If set to true, all editing tools will be disabled and attempts to use them will result in an error -# Added on 2025-04-18 -read_only: false - -# list of tool names to exclude. -# This extends the existing exclusions (e.g. from the global configuration) -# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html -excluded_tools: [] - -# initial prompt for the project. It will always be given to the LLM upon activating the project -# (contrary to the memories, which are loaded on demand). -initial_prompt: "" -# the name by which the project can be referenced within Serena -project_name: "airconsole-unity-plugin" - -# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default). -# This extends the existing inclusions (e.g. from the global configuration). -# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html -included_optional_tools: [] - -# list of mode names that are to be activated by default, overriding the setting in the global configuration. -# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes. -# If the setting is undefined/empty, the default_modes from the global configuration (serena_config.yml) apply. -# Otherwise, this overrides the setting from the global configuration (serena_config.yml). -# Therefore, you can set this to [] if you do not want the default modes defined in the global config to apply -# for this project. -# This setting can, in turn, be overridden by CLI parameters (--mode). -# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes -default_modes: - -# list of mode names to be activated additionally for this project, e.g. ["query-projects"] -# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes. -# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes -added_modes: - -# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. -# This cannot be combined with non-empty excluded_tools or included_optional_tools. -# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html -fixed_tools: [] - -# time budget (seconds) per tool call for the retrieval of additional symbol information -# such as docstrings or parameter information. -# This overrides the corresponding setting in the global configuration; see the documentation there. -# If null or missing, use the setting from the global configuration. -symbol_info_budget: - -# The language backend to use for this project. -# If not set, the global setting from serena_config.yml is used. -# Valid values: LSP, JetBrains -# Note: the backend is fixed at startup. If a project with a different backend -# is activated post-init, an error will be returned. -language_backend: - -# line ending convention to use when writing source files. -# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) -# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. -line_ending: - -# list of regex patterns which, when matched, mark a memory entry as read‑only. -# Extends the list from the global configuration, merging the two lists. -read_only_memory_patterns: [] - -# list of regex patterns for memories to completely ignore. -# Matching memories will not appear in list_memories or activate_project output -# and cannot be accessed via read_memory or write_memory. -# To access ignored memory files, use the read_file tool on the raw file path. -# Extends the list from the global configuration, merging the two lists. -# Example: ["_archive/.*", "_episodes/.*"] -ignored_memory_patterns: [] - -# advanced configuration option allowing to configure language server-specific options. -# Maps the language key to the options. -# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available. -# No documentation on options means no options are available. -ls_specific_settings: {} - -# list of additional workspace folder paths for cross-package reference support (e.g. in monorepos). -# Paths can be absolute or relative to the project root. -# Each folder is registered as an LSP workspace folder, enabling language servers to discover -# symbols and references across package boundaries. -# Currently supported for: TypeScript. -# Example: -# additional_workspace_folders: -# - ../sibling-package -# - ../shared-lib -additional_workspace_folders: [] From 50419d8dc5733e0c2d813220737036ab8c692286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Sch=C3=A4rer?= <143824611+marc-n-dream@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:58:35 +0200 Subject: [PATCH 3/4] e: Update gitignore --- .gitignore | 54 ++++++------------------------------------------------ 1 file changed, 6 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index a5c671ec..57c04a6d 100644 --- a/.gitignore +++ b/.gitignore @@ -87,51 +87,9 @@ ai-setup-backup-*.tar.gz .serena/ .state/ .worktrees/ - -# framework-local state roots -.compound-engineering/* -!.compound-engineering/plans/ -!.compound-engineering/plans/** -!.compound-engineering/brainstorms/ -!.compound-engineering/brainstorms/** -!.compound-engineering/solutions/ -!.compound-engineering/solutions/** -!.compound-engineering/knowledge/ -!.compound-engineering/knowledge/** -!.compound-engineering/evidence/ -!.compound-engineering/evidence/** -!.compound-engineering/specs/ -!.compound-engineering/specs/** -!.compound-engineering/*.md -!.compound-engineering/*.example.yaml -.sisyphus/* -!.sisyphus/plans/ -!.sisyphus/plans/** -!.sisyphus/brainstorms/ -!.sisyphus/brainstorms/** -!.sisyphus/solutions/ -!.sisyphus/solutions/** -!.sisyphus/knowledge/ -!.sisyphus/knowledge/** -!.sisyphus/evidence/ -!.sisyphus/evidence/** -!.sisyphus/specs/ -!.sisyphus/specs/** -!.sisyphus/*.md -!.sisyphus/*.example.yaml -.planning/* -!.planning/plans/ -!.planning/plans/** -!.planning/brainstorms/ -!.planning/brainstorms/** -!.planning/solutions/ -!.planning/solutions/** -!.planning/knowledge/ -!.planning/knowledge/** -!.planning/evidence/ -!.planning/evidence/** -!.planning/specs/ -!.planning/specs/** -!.planning/*.md -!.planning/*.example.yaml -# END idream-managed agent workspace +.claude/worktrees/ +.claude/*.local.json +.omc/ +.compound-engineering/ +.sisyphus/ +.planning/ \ No newline at end of file From 835e708d2400f75e9a194fc16f59a8a3d61fe43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Sch=C3=A4rer?= <143824611+marc-n-dream@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:01:59 +0200 Subject: [PATCH 4/4] Address PR review feedback (#160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .githooks/pre-commit: fail closed when the checker script is missing (was exit 0) - .githooks/pre-merge-commit: new — the guard now runs on merge commits too - .github/workflows/no-proprietary-source.yml: scope GITHUB_TOKEN to contents: read - scripts/check-proprietary-source.sh: deny *.iml / .idea/{modules,misc,gradle}.xml - AGENTS.md + script header: document the .mm exception (upstream unity-webview, zlib licence) instead of leaving it an unexplained gap in the private-source claim - .gitignore: restore trailing newline Co-Authored-By: Claude Opus 5 (1M context) --- .githooks/pre-commit | 8 ++++---- .githooks/pre-merge-commit | 12 ++++++++++++ .github/workflows/no-proprietary-source.yml | 4 ++++ .gitignore | 2 +- AGENTS.md | 6 +++--- scripts/check-proprietary-source.sh | 9 +++++++++ 6 files changed, 33 insertions(+), 8 deletions(-) create mode 100755 .githooks/pre-merge-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit index a87a81fb..84952f69 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -10,9 +10,9 @@ set -euo pipefail repo_root="$(git rev-parse --show-toplevel)" checker="$repo_root/scripts/check-proprietary-source.sh" -if [ ! -x "$checker" ]; then - echo "pre-commit: $checker missing or not executable; skipping guard." >&2 - exit 0 +if [ ! -f "$checker" ]; then + echo "pre-commit: $checker is missing — refusing to commit without the guard." >&2 + exit 1 fi staged=() @@ -24,4 +24,4 @@ if [ "${#staged[@]}" -eq 0 ]; then exit 0 fi -"$checker" "${staged[@]}" +bash "$checker" "${staged[@]}" diff --git a/.githooks/pre-merge-commit b/.githooks/pre-merge-commit new file mode 100755 index 00000000..a7de72d8 --- /dev/null +++ b/.githooks/pre-merge-commit @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# +# pre-merge-commit: git does NOT run pre-commit for merge commits, so a +# `git merge` that brings in proprietary source would otherwise slip past the +# local guard entirely. This repo vendors third-party sources (unity-webview), +# which makes merging an upstream branch a routine operation — exactly the case +# that needs covering. Delegates to the same check as pre-commit. +# +# Enable with: git config core.hooksPath .githooks +set -euo pipefail + +exec bash "$(git rev-parse --show-toplevel)/.githooks/pre-commit" diff --git a/.github/workflows/no-proprietary-source.yml b/.github/workflows/no-proprietary-source.yml index 847ea8db..1353be75 100644 --- a/.github/workflows/no-proprietary-source.yml +++ b/.github/workflows/no-proprietary-source.yml @@ -17,6 +17,10 @@ on: jobs: no-proprietary-source: runs-on: ubuntu-latest + # Read-only gate: it only ever scans the tree, so it must not be able to + # write to it. Do not widen without a concrete reason. + permissions: + contents: read steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 57c04a6d..1500dd16 100644 --- a/.gitignore +++ b/.gitignore @@ -92,4 +92,4 @@ ai-setup-backup-*.tar.gz .omc/ .compound-engineering/ .sisyphus/ -.planning/ \ No newline at end of file +.planning/ diff --git a/AGENTS.md b/AGENTS.md index 575889c4..956dcd65 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -94,9 +94,9 @@ PostprocessBuild auto runs during Unity build. Export package: use Unity export package workflow for `.unitypackage`. Run tests: use Unity Test Runner for EditMode and PlayMode suites. ## PROPRIETARY-SOURCE GUARD -This repo is PUBLIC. Native Android and webview source is PRIVATE and ships here only as compiled artifacts. -NEVER commit native source or the private build system: `*.java`, `*.kt`, Gradle files, `*.sh`/`Rakefile`/`*.rake` build scripts, `*.toml` version catalogs, `AndroidManifest.xml`, `src/main/res/`. -Only compiled artifacts (`.aar`, `.unitypackage`, `.bundle`) and glue (`.cs`, `.jslib`, `.mm`) belong here. +This repo is PUBLIC. AirConsole-authored native Android and webview source is PRIVATE and ships here only as compiled artifacts. +NEVER commit native source or the private build system: `*.java`, `*.kt`, Gradle files, `*.sh`/`Rakefile`/`*.rake` build scripts, `*.toml` version catalogs, `AndroidManifest.xml`, `src/main/res/`, `*.iml`/`.idea/` project files. +Only compiled artifacts (`.aar`, `.unitypackage`, `.bundle`) and glue (`.cs`, `.jslib`) belong here. The sole `.mm` exception is `Assets/AirConsole/unity-webview/Plugins/iOS/*.mm` — third-party upstream (GREE / Takahashi, zlib), public by licence. Never add AirConsole-authored native code as `.mm`. `scripts/check-proprietary-source.sh` is the shared denylist check. CI `.github/workflows/no-proprietary-source.yml` is the authoritative gate; it scans every push (any branch) and PR. Enable the fast local pre-commit guard once per clone: `git config core.hooksPath .githooks`. diff --git a/scripts/check-proprietary-source.sh b/scripts/check-proprietary-source.sh index 4622d987..a62ec4aa 100755 --- a/scripts/check-proprietary-source.sh +++ b/scripts/check-proprietary-source.sh @@ -14,6 +14,11 @@ # - WebViewPlugin-*.aar.tmpl (webview native, compiled) # - *.unitypackage / *.bundle (compiled) # +# ONE EXCEPTION, already in the tree: Assets/AirConsole/unity-webview/Plugins/ +# iOS/*.mm is third-party upstream (GREE / Keijiro Takahashi, zlib licence) and +# is public by licence, not by mistake. That is why *.mm is not on the denylist. +# AirConsole-authored native code must NEVER be added as *.mm. +# # Source languages (*.java, *.kt), the Gradle build system, and the private # build pipeline (shell/Rake scripts, version catalogs) reveal the internal # technology and MUST NOT be committed here. A leak is effectively @@ -64,6 +69,8 @@ DENY_PATTERN=( "(^|/)\.gitmodules$S" "(^|/)AndroidManifest\.xml$S" "(^|/)src/main/res/" + "\.iml$S" + "(^|/)\.idea/(modules|misc|gradle)\.xml$S" ) DENY_REASON=( 'native source (Java/Kotlin) — ships as a compiled .aar, never as source' @@ -79,6 +86,8 @@ DENY_REASON=( 'submodule reference — would disclose a private repository URL' 'native Android manifest — declares internal components/permissions' 'native Android resources — belong to the private library' + 'IntelliJ/Android Studio module file — reveals the private dependency stack' + 'IntelliJ/Android Studio project config — reveals the private module layout' ) # --- Allowlist: the ONLY exceptions to the denylist above --------------------