Last Week
Last week was about trying to get Shokken ready for the “real world” instead of just the “builder world”. The alpha builds are in a good place on both Android and iOS, and I’m still shipping weekly updates as bugs and rough edges show up from testers.
The big non-app milestone was the product website: getting it to the point where it explains what Shokken is, what problem it solves, and what the next step is for a restaurant that’s curious. I got most of the way there, but I didn’t finish the last mile: the screenshots and short demo clip that make it feel real instead of “a nice landing page”.
The Week I Tried to “Improve the Workflow”
This week was supposed to be straightforward: finish the product website, keep fixing bugs, keep tightening the release.
Instead, I did the thing I always warn myself about: I started sharpening tools.
There’s a genuine motivation here. Kotlin Multiplatform builds are heavy, and the project is at the stage where small mistakes still happen: a missing import, a slightly wrong API call, a change that compiles on one target but not another. When each “check the build, run the tests, ship the update” loop is expensive, it becomes tempting to invest in a more repeatable path from “I made a change” to “this is safe to ship”.
But the tool-sharpening trap is that it has no natural stopping point. You can always add one more safety check, one more gate, one more “nice to have” improvement to the process. The result is a week where you do a lot of work, learn a lot, and still don’t ship the thing you said you were going to ship.
That’s basically Week 58.
The Security Tripwire: Don’t Let CI Impersonate You
The most useful lesson of the week had nothing to do with performance. It was about credentials.
If your build system can “act like you” (write to the repo, post as you, trigger privileged actions), you’ve quietly turned CI into a high-value target. One leaked token, one compromised dependency, one mistake in a workflow trigger, and you’ve handed out the keys to the project.
The rule I’m taking away is simple:
- CI should use the smallest permissions possible.
- Anything that requires “human-level” access should be a separate, tightly controlled path.
That mindset forces you to separate “verification” (builds, tests, lint) from “privileged operations” (publishing, writing to protected branches, minting releases, or anything that could damage the repo if abused).
The Physics Problem: Build Times Are Real
The second lesson is less dramatic but just as real: the runtime cost of verification sets the pace of the entire project.
On my machine, a full verification pass is in the “minutes” category. On a slower environment, or one without warm caches, it can stretch into “go do something else and come back later”. When the verification loop gets that long, every experiment turns into a commitment, and it becomes much easier to justify process work instead of feature work.
This is also where platform reality shows up. If part of your pipeline requires macOS (iOS builds/signing), you either pay for hosted macOS time or you take ownership of your own runners. Either way, that constraint shapes what’s practical to run on every change.
What does it mean in English?
This week was about a very normal kind of procrastination: “I’m not avoiding work, I’m improving the process.”
There’s a version of that mindset that’s healthy. Better release hygiene matters, and repeatable verification is how you avoid embarrassing regressions.
But there’s also a version of it that’s a trap: you can spend infinite time perfecting the workflow while the actual product tasks (like finishing the website screenshots) sit untouched.
The real progress this week was internal: I got a lot clearer on where the line is between safe verification and risky “keys to the kingdom” operations. And I got a reminder that the only workflow improvement that matters is the one that helps you ship.
Nerdy Details
Practical rule: CI should never have “human” credentials
If a credential can write to your repo, create releases, or otherwise behave like a developer account, treat it like production access. Don’t sprinkle it into general-purpose workflows.
Prefer short-lived, tightly scoped credentials:
- Use the default workflow token with minimal permissions for reads and status checks.
- Keep write permissions out of build/test jobs unless there’s a very specific, reviewed reason.
- Put anything privileged behind manual triggers and protected environments.
The sharp edge here is that CI runs code you don’t fully control: dependencies, build tooling, and sometimes code from branches you didn’t write. If that code can access “real” credentials, you’ve created a very expensive mistake.
A minimal-permissions GitHub Actions shape
Here’s the shape I’m moving toward: verification jobs that only need read access, and privileged jobs that are separate and intentionally gated.
permissions:
contents: read
pull-requests: read
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./gradlew test
The details vary per repo, but the principle holds: start from “read-only” and only add permissions that are clearly required.
Split verification from privileged work
Verification should be boring: compile, test, lint, report status.
Privileged work should be rare: publishing builds, tagging releases, writing back to the repo, or anything that uses long-lived secrets. Those jobs deserve:
- Manual triggers (
workflow_dispatch) or protected branch constraints. - Environment protection rules and required reviewers.
- Separate credentials with narrow scopes.
That separation makes the system easier to reason about, and it makes mistakes less catastrophic.
KMP makes you respect the feedback loop
Kotlin Multiplatform is worth it for Shokken, but it’s a reminder that “build time” is a first-class product constraint.
When compilation and tests are heavy, your workflow needs to be designed around fast iteration:
- Keep the quick checks quick.
- Run the expensive checks when they’re most valuable (before merges/releases).
- Lean on caching and reproducible builds so the pipeline isn’t punishing by default.
None of that is glamorous, but it’s the difference between shipping weekly updates comfortably and dreading every change.
Next Week
Next week is a return to the obvious work.
I’m finishing the product website: screenshots, a short demo clip, and the final polish so it feels like a real front door to the app. If I have time after that, I want to start on a physical one-pager I can bring to restaurants (and send over email) so pilots don’t depend on “go read a long blog post” as the first step.