No description
  • Scheme 98.2%
  • Shell 1.5%
  • Makefile 0.3%
Find a file
2026-07-30 15:45:50 -06:00
.builds ci: set umask 022 in package/verify tasks too (jerbuild creates group-writable cache dirs during pkg operations) 2026-07-22 13:10:54 -06:00
docs Harden Android generation and supply chain 2026-07-11 17:22:54 -06:00
examples Harden Android generation and supply chain 2026-07-11 17:22:54 -06:00
jandroid Harden Android generation and supply chain 2026-07-11 17:22:54 -06:00
scripts Make typed Android generation self-contained 2026-07-20 03:01:02 -06:00
supply-chain Pin SSD Android runtime dependencies 2026-07-20 02:43:55 -06:00
templates Make typed Android generation self-contained 2026-07-20 03:01:02 -06:00
tests Add positive regression test for Kotlin dollar-template escaping (P1 #32) 2026-07-21 19:06:54 -06:00
tools Add typed client template composition tool 2026-07-19 20:05:33 -06:00
.gitignore Harden Android generation and supply chain 2026-07-11 17:22:54 -06:00
.gitsafe.json Build SSD app with typed Kotlin models 2026-07-15 20:33:41 -06:00
AGENTS.md docs: remove jerboa-emacs restriction 2026-07-30 15:45:50 -06:00
dependencies.lock.json Pin SSD Android runtime dependencies 2026-07-20 02:43:55 -06:00
full-kotlin.md Move SSD OCR center geometry to typed Kotlin 2026-07-15 21:59:22 -06:00
jandroid.ss Confine untrusted spec strings and identifiers inside Kotlin/Gradle literals 2026-07-21 19:06:05 -06:00
jpkg.sexp Add jpkg packaging 2026-07-21 15:08:37 -06:00
Makefile build: add lint target 2026-07-21 11:57:06 -06:00
README.md Document typed production client policy 2026-07-20 02:54:48 -06:00
SECURITY.md Harden Android generation and supply chain 2026-07-11 17:22:54 -06:00

jerboa-android

jerboa-android is an early Android project generator for Jerboa.

The first target is deliberately small: read a quoted Jerboa app spec from a .ss file and emit a plain Kotlin/Android Gradle project. Jerboa runs at build time on the developer machine; the generated APK contains ordinary Android code.

Quick Start

make verify
make clean generate

make verify runs the release-required adversarial and supply-chain checks. make ssd-compile performs the heavier generated-Android compile with the repository-pinned Gradle and JDK artifacts. See SECURITY.md for the trust boundaries and release policy.

The generated counter project is written to build/counter.

Use make apk to regenerate it and build with the authenticated, pinned Gradle and JDK artifacts.

The generated project defaults to Android Gradle Plugin 8.13.2 and Kotlin 2.0.21, because those versions are already used by the larger game app. Specs can override both versions.

App Spec Shape

Specs are valid Jerboa files that define a quoted app value:

(import (jerboa prelude))

(def app
  '(android-app
     (id "org.jerboa.counter")
     (name "Jerboa Counter")
     (version-code 1)
     (version-name "0.1.0")
     (screen Main
       (state count 0)
       (column
         (text "Count: " count)
         (button "Increment" (set count (+ count 1)))))))

Current supported view forms:

  • (column child ...)
  • (row child ...)
  • (text part ...)
  • (button label action ...)
  • (spacer height)
  • (small-text part ...)

Current supported action form:

  • (set state expression)

Current supported expression forms:

  • strings, numbers, booleans, symbols
  • binary +, -, *, /

Android project metadata supported by the generator:

  • (id "com.example.app")
  • (name "Display Name")
  • (root-name "GradleRootName")
  • (compile-sdk 35), (build-tools-version "36.0.0"), (min-sdk 26), (target-sdk 35)
  • (version-code 10), (version-name "0.1.9")
  • (android-gradle-plugin "8.13.2"), (kotlin-version "2.0.21")
  • (jvm-toolchain 17)
  • (gradle-property "android.useAndroidX" "true")
  • (permission "android.permission.INTERNET")
  • (permission "android.permission.READ_EXTERNAL_STORAGE" (max-sdk 32))
  • (allow-backup #t), (uses-cleartext-traffic #t)
  • (theme "@android:style/Theme.Material.NoActionBar")
  • (ndk-version "28.2.13676358"), (abi-filter "arm64-v8a")
  • (asset-dir "relative/path")
  • (jni-lib-dir "relative/path")
  • (dependency "androidx.documentfile:documentfile:1.1.0")
  • (kotlin-source-dir "relative/path")
  • (fragment "relative/path.ss")
  • (client original-tactics)
  • (typed-kotlin-file "relative/File.kt" (typed-library ...))

asset-dir and jni-lib-dir copy directory contents into the generated Android project. This lets app repos keep only Jerboa specs and binary assets under source control while Kotlin remains generated output.

kotlin-source-dir is a migration bridge for existing apps. It copies existing Kotlin source into the generated project after the default generated MainActivity.kt, so a large app can move to Jerboa-owned Android project generation before each view is rewritten as higher-level Jerboa forms.

fragment reads another Jerboa file that defines:

(def fragment
  '((kotlin-file "com/example/Extra.kt" "package com.example\n...")))

Large fragments can use line lists instead of one string:

(def fragment
  '((kotlin-file-lines "com/example/Extra.kt"
      ("package com.example"
       ""
       "class Extra"))))

Fragments are expanded into the app spec before generation. They are useful for large generated source sets that should stay in .ss files instead of the main app spec.

typed-kotlin-file emits a normal Typed Jerboa typed-library through the upstream (jerboa typed kotlin) backend. Use it for new generated Kotlin instead of kotlin-file, kotlin-file-lines, or kotlin-source-dir. When generated records need JVM/Android types, add structured imports before the library form:

(typed-kotlin-file "com/example/Pick.kt"
  (kotlin-imports (android net Uri))
  (typed-library (com example)
    (export make-Pick Pick? Pick-uri)
    (type Uri)
    (record Pick ((uri : Uri)))))

client expands a named generator-owned template from templates/<name>.ss. The original-tactics and ssd-review clients are composed exclusively from typed Jerboa libraries. Their generated Kotlin is backend output, not source text stored in .ss strings. scripts/check-no-raw-kotlin.sh enforces that invariant for both production clients.

All source paths are relative to the app specification and may not contain symbolic links. Output paths are descriptor-relative, no-follow, exclusive creates; generation intentionally fails if a target already exists. Dependency coordinates must use an exact group:name:version (no +, ranges, latest, or snapshot selectors). Generated projects include strict Gradle verification metadata for the reviewed graph; adding a dependency also requires a reviewed checksum update (or an application-owned verification manifest) before Gradle will execute the build. The generated settings also constrain known-vulnerable transitive build dependencies to the reviewed versions recorded in dependencies.lock.json.

The ssd-review client keeps remote synchronization disabled by default. A deployment must locally provision an HTTPS origin, SPKI SHA-256 pin, and bearer token; remote identifiers are hashed into local filenames and all HTTP, ZIP, entry-count, expansion-ratio, and storage budgets are enforced. The precise configuration and limits are documented in SECURITY.md.

Production Client Policy

New production Android code must use typed-kotlin-file or a typed named client module. Raw kotlin-file, kotlin-file-lines, and kotlin-source-dir forms remain only as compatibility features for generic generator fixtures; they are not permitted in Original Space Tactics or SSD Review.