- `make release VERSION=vX.Y.Z` checks the tree is clean, pushes HEAD,
tags, pushes the tag, then runs update-sdk so every downstream repo's
go.mod gets bumped in one shot.
- SDK_DOWNSTREAM_DIRS now includes orchestrator/backend and
blockninja-themes/* (globbed), which were both missing previously.
- ninja login forces account selection (interactive when >1); creds now
carry ActiveAccountID/Slug. New `ninja account` group.
- ninja plugin list / delete / delete-version split public vs active-account
@private sections; `publish --private` is sticky in plugin.mod.
- GetPluginRequest gains active_account_id so @private resolution works
alongside the public (scope, name) path.
- publish auto-commits a dirty plugin.mod (path-scoped, leaves other staged
paths alone) so the bump→publish loop never trips the dirty check.
--allow-dirty is replaced with --strict (default now ships dirty trees
via stash-create).
- bump auto-commits its plugin.mod write with `bump to X.Y.Z`; --no-commit
opts out.
- Design doc updated to match the new defaults.
Add private-plugin RPCs (ListPrivatePlugins, DeletePrivatePlugin,
DeletePrivatePluginVersion, ListPrivatePluginInstallSites) and
ListMyAccounts to the proto/generated stubs; introduce PluginVisibility
enum replacing the loose string field; add ModPlugin.Private + Coords()
routing to @private/<name>@<version>; update ninja CLI to use
VisibilityLabel helper; bump go directive to 1.26.4 for ABI alignment.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Proves the publish command's warning surface end-to-end: tracked-yet-
gitignored files, declared submodules, untracked files on --allow-dirty,
and that the dirty-tree abort suppresses the untracked warning.
Pulls the three warning calls and the dirty-tree check out of the
publish RunE closure into a single helper so a refactor that drops one
warning can be caught by a fixture-based test.
Adds coverage for two git-edge cases: commits land correctly on a
detached HEAD with the prior commit as parent, and an empty PATH
produces a git-mentioning error rather than a panic.
Add fires/no-op pairs for gitignoredTrackedWarning, untrackedFilesWarning,
and submoduleWarning. The submodule case writes a hand-crafted .gitmodules
file rather than wiring real submodules — submodulePaths reads the file
directly so that's sufficient.
Pull the three inline warning blocks in newPluginPublishCmd —
gitignoredTrackedWarning, untrackedFilesWarning, submoduleWarning — into
package-private helpers that take a repo dir and an io.Writer. Output is
byte-identical to the previous inline code; this just makes them unit-
testable without driving the whole cobra command.
autoCommitPluginMod runs `git status --porcelain plugin.mod` then commits if
dirty. Add two cases: dirty plugin.mod produces an "Add plugin.mod" commit,
and a clean state leaves HEAD unchanged. Uses t.Chdir to scope CWD to the
temp repo without polluting parent state.
The dirty-tree branch (where git stash create captures uncommitted tracked
changes) was untested. Add two cases: one asserting the archive contains
the dirty working-copy contents (not HEAD) and the working tree is not
mutated; another asserting untracked files are excluded — the contract
the --allow-dirty publish warning relies on.
`git archive` does not recurse into submodules, so a plugin shipping
vendored code via submodule produced a tarball where the submodule path
existed but was empty — silent failure. Now publish reads .gitmodules
and lists submodule paths to stderr with guidance to vendor or pack
them separately. The publish still proceeds, since the developer may
not actually need the submodule contents in the archive.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`git stash create` only captures tracked content, so a developer using
--allow-dirty after creating new files (but forgetting to `git add`)
would ship a tarball missing them with no indication. Now publish lists
the untracked, non-ignored files to stderr and suggests `git add` when
--allow-dirty is in play.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously a brand-new repo (git init, no commits) surfaced `git stash
create: exit status 128: You do not have the initial commit yet` from
deep inside the archive helper. Now the publish flow detects this case
via `git rev-parse --verify HEAD` up front and prints "no commits in
repository; run `git add . && git commit` before publishing". Also
updates the init flow's hint to mention `git init && git commit` so
users aren't misled into thinking `git init` alone is enough.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a doc comment to ModFile.Coords explaining the leading-@ trim and a
note on ModPlugin.Scope clarifying that consumers should trim "@" before
comparing. Locks in the contract with a test asserting both call shapes
produce the same display string.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pre-existing CLI improvements ahead of the tarball-publish refactor:
- New top-level `ninja scope` command (create, list, set-default).
- `init` accepts no --scope: prompts from ListMyScopes or uses creds default.
- Plugin name prompted if not provided.
- `plugin bump <major|minor|patch>` writes the bumped version into plugin.mod.
- `plugin version` prints the current plugin.mod version.
- `login` prints a URL with ?user_code= so the link is one click.
- creds: HostCreds gains optional default_scope.
- plugin/version: ParseBaseSemver + BumpVersion helpers, with tests.
Design for two coupled changes: drop git as the publish transport in
favour of tar.zst uploads, and add a first-class plugin kind plus a
configurable, validated category list.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Decouple TemplateFunc from templ.Component by introducing a generic
HTMLComponent interface that both templ and pongo2 satisfy via Go
structural typing. Add a complete pongo2 rendering engine in
templates/pongo/ with page templates, block templates (with BlockContext
injection and icon processing), template overrides, and email wrappers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Plain-text nodes inside paragraphs, headings, lists and table cells now
auto-wrap any https:// URL in <a href="..." rel="noopener">URL</a>.
- Bare domains, www. and http:// URLs are intentionally not linked
- Suppressed inside explicit `link` inline nodes (no nested anchors)
- Suppressed inside `code`-styled spans (URL stays literal)
- Trailing sentence punctuation (.,;:!?'") is excluded from the linked URL
- Closing parens/brackets/braces are kept inside the URL only when
balanced with an opener (so Wikipedia-style _(bar) is preserved
but `(see https://x.com)` doesn't eat the trailing paren)
- Bold/italic/color style wrappers compose around the anchor
`renderInlineContent` gains an `insideLink bool` parameter; all existing
call sites pass `false`, and the `link` branch recurses with `true`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SDK renderer now has full feature parity with the host: text alignment,
checkListItem, toggleListItem, video, audio, file, statement blocks,
and text/background color inline styles. New datasources.Datasources
interface lets plugins resolve buckets directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Defines cross-plugin seeder interfaces in the SDK so template plugins
can seed Symposium/Messenger content via PluginBridge without importing
their database packages directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enables runtime plugin disable/enable without CMS restart.
Load is called after registration succeeds; Unload on disable
with a 30-second context deadline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The provisioner just marshals the value to JSON regardless of type.
Restricting to map[string]any prevented plugins from setting scalar
field values (strings, numbers, booleans).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>