The install was the product
KeyControl was a portability problem.
I thought I was cleaning up an old add-on. I was really pulling its install steps out of memory so somebody else could run and check it.
KeyControl needs WebCentral around it. The app, UI, database scripts, overlay files, license path, Tomcat version, Java version, and support checks all have to line up. Miss one and the install isn't trustworthy.
The repo had server and UI source, a WebCentral overlay, SQL Server scripts, a Java SQL runner, validation tools, and shell entrypoints. This wasn't a folder of old views to clean up. The install path was part of the product, even though too much of it still lived in habit.
The workspace exposed the boundary. WebCentral has to be the main runtime checkout, while KeyControl stays in its own repo. The deployed UI goes under the WebCentral app. The source repo doesn't. Mix those up and the first QA pass lies.
A workspace had to check out WebCentral, check out KeyControl, deploy KeyControl before validation, and leave proof for the next person. Until it could do that, the product was still living in memory.
A clean build didn't solve this. Somebody else had to install KeyControl, test it, and explain what happened without borrowing my setup.
Two WebCentral lines had to keep working.
"Modernize it" doesn't say which runtime has to work. One KeyControl line still targets
Tomcat 9, Java 11, and javax.servlet. The newer line targets Tomcat 10,
Java 21, and jakarta.servlet. The package-name change looks small right up
until the jar is built against the wrong WebCentral libraries.
The scripts inspect the WebCentral root and pick t9 or t10.
They also allow an explicit override when detection isn't enough. Nobody has to remember
the target before running them. Old products need that kind of boring behavior.
The database work had to be rerunnable.
The SQL Server path has an install manifest: core, background data, then example data. Its notes are blunt. There is no schema history table and no deploy log, so every script has to be safe to run again.
Fresh installs need full objects. Upgrade reruns need guarded backfills. Where possible, metadata has to come from the target database instead of guesses baked into a script. A small Java runner applies the manifest with the right JDBC driver. That replaces one more copy-paste ritual.
Read the WebCentral root and database shape.
Build the server jar against the target libraries.
Sync only the overlay files named in the manifest.
Apply SQL through the runner, not a memorized habit.
Restart Tomcat and wait for WebCentral plus KeyControl.
The package had to carry the install story.
The release package had to work without me standing beside it. It needs the overlay, UI build, and server jar for the right runtime. It also needs database scripts, the SQL runner, a place for JDBC drivers, and the legacy license file path KeyControl still uses.
The license details don't belong in public. The operating problem does. If somebody must remember which jar to pick, which files to copy, where the UI goes, and when to run SQL, the package still isn't carrying enough of KeyControl.
The support bug was useful evidence.
A failed helper is sometimes better evidence than a clean demo.
Permissions are part of the product.
The database reset helper existed, but the workspace supervisor couldn't read the metadata it needed. A separate cleanup stopped preserving group execute bits, which made product scripts harder to run from the shared support path.
Giving everything more access would have hidden the bug. The narrow fix kept raw credentials private, made generated database metadata readable to the shared group, preserved executable bits, and made the helper path usable from the supervisor context.
The smoke check mattered because it was plain. WebCentral returned 200. The KeyControl route returned 200. The supervisor-side reset helper could show usage output instead of failing before it started.
If support tools depend on a permission accident, they are not support tools yet.
The workspace had to prove the repo stack.
CI can't validate KeyControl as if it runs alone. The runner launches WebCentral first, checks out KeyControl as the product repo, deploys KeyControl before validation, and then collects evidence from the combined system.
This catches failures that source review misses. Browser readiness, login, database restore, runtime logs, static checks, ArchiBot QA, and destination validation all need the same stack. Otherwise the review stares at source while the failure sits in the runtime.
That pain led to the repo stack preview in Console. It shows the runtime repo, product repo, checkout order, branch, path, and deploy-before-validation command. "Two repositories" isn't enough when one is the room and the other is what gets installed in it.
With those details visible, a new person can inspect the package, run the install, and know what to check before saying it worked.
Old repos remember what the product survived.
Old product repos keep the parts people had to fight to preserve: database shape, release packages, platform upgrades, license handling, deploy habits, support helpers, and the checks that say whether an install worked.
A zip file doesn't make any of that portable. The package has to name where the source lives, what gets copied, which runtime it targets, how SQL runs, and which page checks must pass.
KeyControl needed fewer steps that only one person knew. Put them in the package, run them, and keep the proof.