Files
HarborForge/plans/harborforge-cli-go-plan.md

18 KiB

HarborForge CLI (hf) Plan

Goal

Build a Go-based HarborForge CLI binary named:

hf

This CLI should work well in two environments:

  1. With padded-cell / pass_mgr available
    • agents can execute commands directly
    • secrets and generated credentials are resolved automatically
  2. Without padded-cell installed
    • humans can still use the CLI manually by explicitly passing tokens or account-manager credentials

Important: do not directly migrate the old Python CLI from HarborForge.Backend/cli.py as-is. That old CLI is only a reference for command inventory. The new CLI must be a standalone Go binary.


High-Level Direction

  • Language: Go
  • Delivery: single binary
  • Config file: .hf-config.json
  • Config location: same directory as the CLI binary
  • Secret integration: pass_mgr
  • Command style: grouped subcommands (hf user ..., hf task ..., hf monitor ...)
  • Identifiers: prefer codes/names instead of internal numeric ids whenever possible
    • project-code
    • milestone-code
    • task-code
    • meeting-code
    • support-code
    • role-name
    • username

Binary / Config Model

CLI name

hf

Config file location

hf must resolve its config file relative to the binary directory, not cwd and not home directory.

The command:

hf config --url <hf-url>

must write:

{
  "base-url": "<hf-url>"
}

into:

<binary-dir>/.hf-config.json

Initial config structure

{
  "base-url": "http://127.0.0.1:8000"
}

The config file should remain intentionally minimal at first.


Runtime Mode Detection

At startup, the CLI must check whether pass_mgr exists:

which pass_mgr

This determines the CLI mode.

Mode A — padded-cell / pass_mgr installed

If which pass_mgr succeeds:

  • the CLI runs in automatic secret mode
  • users/agents should not explicitly provide --token or --acc-mgr-token
  • help output should not show those flags
  • if a caller explicitly provides such flags, terminate with:
padded-cell installed, --token flag disabled, use command directly

This message is also used for other manual credential flags that should be suppressed in padded-cell mode.

Token sources in padded-cell mode

For normal authenticated commands:

pass_mgr get-secret --key hf-token

For account-manager flow:

pass_mgr get-secret --public --key hf-acc-mgr-token

For password generation during user creation:

pass_mgr generate --key hf --username <username>

Mode B — no padded-cell / no pass_mgr

If which pass_mgr fails:

  • assume padded-cell is not installed
  • manual auth flags become required where needed
  • help output must explicitly show the required flags
  • commands that require token/account-manager credentials must state that clearly in --help

Help System Rules

1. hf --help

  • does not require --token
  • does not require pcexec
  • shows all top-level command groups

2. hf --help-brief

  • does not require --token
  • does not require pcexec
  • shows only currently permitted top-level command groups

3. hf <group> --help

Show all subcommands in the group.

  • If permitted: show subcommand name + description
  • If not permitted: show subcommand name + (not permitted)
  • For not-permitted subcommands, do not show detailed usage or flag descriptions

Example:

hf user --help

list        List users
get         Show a user by username or id
create      Create a user account (uses account-manager token flow)
update      (not permitted)
activate    (not permitted)
deactivate  (not permitted)
delete      (not permitted)

4. hf <group> --help-brief

Show only currently permitted subcommands.

Example:

hf user --help-brief

list        List users
get         Show a user by username or id
create      Create a user account (uses account-manager token flow)

5. hf <group> <subcommand> --help

  • If permitted: show full help
  • If not permitted: show only a short message such as:
hf user update: not permitted

No detailed usage, no flags, no examples.

6. hf <group> <subcommand> --help-brief

For leaf commands, this behaves the same as --help:

  • permitted → full help
  • not permitted → short not permitted message only

7. Mode-sensitive help

padded-cell mode

  • hide --token
  • hide --acc-mgr-token
  • hide other manual credential flags that should not be used directly

manual mode

  • show required credential flags where needed
  • clearly indicate commands that require --token
  • clearly indicate user create special requirements

Credential / Auth Rules

Normal authenticated commands

For most resource commands, auth behaves like this:

padded-cell mode

  • do not accept --token
  • auto-read token using:
pass_mgr get-secret --key hf-token

manual mode

  • --token <token> becomes required
  • if missing, terminate with:
--token <token> required or execute this with pcexec

Special command: hf user create

hf user create is special.

It does not use the normal user token flow. It uses account-manager token flow.

Command shape:

hf user create --user <username> [--pass <password>] [--email <email>] [--full-name <name>] [--acc-mgr-token <token>]

Rules

  • no --token
  • no --role
  • default role is always guest

padded-cell mode

  • do not show --acc-mgr-token
  • do not allow callers to pass --acc-mgr-token
  • password fallback:
pass_mgr generate --key hf --username <username>
  • account-manager token fallback:
pass_mgr get-secret --public --key hf-acc-mgr-token

If password generation fails:

--pass <password> required or execute with pcexec

If account-manager token lookup fails:

--acc-mgr-token <token> required or execute with pcexec

manual mode

  • --acc-mgr-token must be shown in help
  • --pass may be omitted only if running with pcexec / pass_mgr-compatible flow
  • otherwise use the same exact failure messages above

Special help behavior

Even if the current user token lacks normal user-write permission, hf user create may still appear as available because it is a distinct account-manager token flow.


Config Commands

1. Configure HarborForge URL

hf config --url <hf-url>

Behavior:

  • write/update base-url in <binary-dir>/.hf-config.json

2. Configure account-manager token

hf config --acc-mgr-token <token>

Behavior:

  • execute:
pass_mgr set --public --key hf-acc-mgr-token --secret <token>

If this fails:

--acc-mgr-token can only be set with padded-cell plugin

Supported Command Tree

This section defines the intended command surface.


A. Base Commands

hf version

hf version

hf health

hf health

No separate auth/login command group is planned. Authentication is entirely handled through padded-cell/pass_mgr mode or explicit manual flags.


B. User Commands

hf user create

hf user create --user <username> [--pass <password>] [--email <email>] [--full-name <name>] [--acc-mgr-token <token>]

hf user list

hf user list [--token <token>]

hf user get

hf user get <username|user-id> [--token <token>]

hf user update

hf user update <username|user-id> [--email <email>] [--full-name <name>] [--pass <password>] [--active <true|false>] [--token <token>]

hf user activate

hf user activate <username|user-id> [--token <token>]

hf user deactivate

hf user deactivate <username|user-id> [--token <token>]

hf user delete

hf user delete <username|user-id> [--token <token>]

hf user worklogs is not planned.


C. Role / Permission Commands

hf role list

hf role list [--token <token>]

hf role get

hf role get <role-name> [--token <token>]

hf role create

hf role create --name <role-name> [--desc <desc>] [--global <true|false>] [--token <token>]

hf role update

hf role update <role-name> [--desc <desc>] [--token <token>]

hf role delete

hf role delete <role-name> [--token <token>]

hf permission list

hf permission list [--token <token>]

hf role set-permissions

hf role set-permissions <role-name> --permission <perm> [--permission <perm> ...] [--token <token>]

hf role add-permissions

hf role add-permissions <role-name> --permission <perm> [--permission <perm> ...] [--token <token>]

hf role remove-permissions

hf role remove-permissions <role-name> --permission <perm> [--permission <perm> ...] [--token <token>]

D. Project Commands

hf project list

hf project list [--owner <username>] [--order-by <created|name>] [--order-by <...>] [--token <token>]

hf project get

hf project get <project-code> [--token <token>]

hf project create

hf project create --name <name> [--desc <desc>] [--repo <repo>] [--token <token>]

hf project update

hf project update <project-code> [--name <name>] [--desc <desc>] [--repo <repo>] [--token <token>]

hf project delete

hf project delete <project-code> [--token <token>]

hf project members

hf project members <project-code> [--token <token>]

hf project add-member

hf project add-member <project-code> --user <username> --role <role-name> [--token <token>]

hf project remove-member

hf project remove-member <project-code> --user <username> [--token <token>]

E. Milestone Commands

hf milestone list

hf milestone list --project <project-code> [--status <status>] [--order-by <due-date|created|name>] [--order-by <...>] [--token <token>]

hf milestone get

hf milestone get <milestone-code> [--token <token>]

hf milestone create

hf milestone create --project <project-code> --title <title> [--desc <desc>] [--due <date>] [--token <token>]

hf milestone update

hf milestone update <milestone-code> [--title <title>] [--desc <desc>] [--status <status>] [--due <date>] [--token <token>]

hf milestone delete

hf milestone delete <milestone-code> [--token <token>]

hf milestone progress

hf milestone progress <milestone-code> [--token <token>]

F. Task Commands

hf task list

hf task list [--project <project-code>] [--milestone <milestone-code>] [--status <status>] [--taken-by <me|null|username>] [--due-today <true|false>] [--order-by <due-date|priority|created|name>] [--order-by <...>] [--token <token>]

Defaults:

  • --taken-by me
  • --due-today false
  • --order-by due-date

hf task get

hf task get <task-code> [--token <token>]

hf task create

hf task create --project <project-code> --title <title> [--milestone <milestone-code>] [--type <type>] [--priority <priority>] [--desc <desc>] [--token <token>]

hf task update

hf task update <task-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>] [--assignee <username|null>] [--token <token>]

hf task transition

hf task transition <task-code> <status> [--token <token>]

hf task take

hf task take <task-code> [--token <token>]

Behavior:

  • assign the task to the current user
  • if already taken by another user or permission rules block the change, return a clear error

hf task delete

hf task delete <task-code> [--token <token>]
hf task search --query <text> [--project <project-code>] [--status <status>] [--token <token>]

G. Meeting Commands

Meeting logic is task-like, but the special action is attend, not take.

hf meeting list

hf meeting list [--project <project-code>] [--status <status>] [--order-by <created|due-date|name>] [--order-by <...>] [--token <token>]

hf meeting get

hf meeting get <meeting-code> [--token <token>]

hf meeting create

hf meeting create --project <project-code> --title <title> [--milestone <milestone-code>] [--desc <desc>] [--time <datetime>] [--token <token>]

hf meeting update

hf meeting update <meeting-code> [--title <title>] [--desc <desc>] [--status <status>] [--time <datetime>] [--token <token>]

hf meeting attend

hf meeting attend <meeting-code> [--token <token>]

Behavior:

  • add the current user to the meeting participant list

hf meeting delete

hf meeting delete <meeting-code> [--token <token>]

H. Support Commands

Support logic is also task-like.

hf support list

hf support list [--taken-by <me|null|username>] [--status <status>] [--order-by <due-date|priority|created|name>] [--order-by <...>] [--token <token>]

hf support get

hf support get <support-code> [--token <token>]

hf support create

hf support create --title <title> [--project <project-code>] [--desc <desc>] [--priority <priority>] [--token <token>]

hf support update

hf support update <support-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>] [--token <token>]

hf support take

hf support take <support-code> [--token <token>]

hf support transition

hf support transition <support-code> <status> [--token <token>]

hf support delete

hf support delete <support-code> [--token <token>]

I. Comment / Worklog Commands

hf comment add

hf comment add --task <task-code> --content <text> [--token <token>]

hf comment list

hf comment list --task <task-code> [--token <token>]

hf worklog add

hf worklog add --task <task-code> --hours <n> [--desc <text>] [--date <yyyy-mm-dd>] [--token <token>]

hf worklog list

hf worklog list [--task <task-code>] [--user <username>] [--token <token>]

J. Propose Commands

hf propose list

hf propose list --project <project-code> [--status <status>] [--order-by <created|name>] [--order-by <...>] [--token <token>]

hf propose get

hf propose get <propose-code|propose-id> [--token <token>]

If propose code does not exist yet in backend, the CLI may temporarily accept ids, but code-based lookup is the target direction.

hf propose create

hf propose create --project <project-code> --title <title> --desc <desc> [--token <token>]

hf propose update

hf propose update <propose-code|propose-id> [--title <title>] [--desc <desc>] [--token <token>]

hf propose accept

hf propose accept <propose-code|propose-id> --milestone <milestone-code> [--token <token>]

hf propose reject

hf propose reject <propose-code|propose-id> [--reason <reason>] [--token <token>]

hf propose reopen

hf propose reopen <propose-code|propose-id> [--token <token>]

K. Monitor Commands

hf monitor overview

hf monitor overview [--token <token>]

hf monitor server list

hf monitor server list [--token <token>]

hf monitor server get

hf monitor server get <server-identifier|server-id> [--token <token>]

hf monitor server create

hf monitor server create --identifier <identifier> [--name <display-name>] [--token <token>]

hf monitor server delete

hf monitor server delete <identifier|server-id> [--token <token>]

hf monitor api-key generate

hf monitor api-key generate <identifier|server-id> [--token <token>]

hf monitor api-key revoke

hf monitor api-key revoke <identifier|server-id> [--token <token>]

Backend / Permission Requirements

The CLI design depends on backend support for a narrow account-manager capability.

Required protected roles

In addition to:

  • admin
  • guest

also protect:

  • account-manager

account-manager semantics

  • default seeded role
  • cannot be deleted
  • should only have the permission:
    • account.create
  • should not inherit general admin powers

Current alignment

The backend should support:

  • single global role per account
  • default guest assignment for normal account creation
  • admin role protected from normal user-management reassignment
  • account-manager flow for creating accounts

Planned Implementation Phases

Phase 1 — Foundation

  • create Go module
  • add binary entrypoint for hf
  • implement config file resolution relative to binary directory
  • add .hf-config.json load/save
  • implement runtime mode detection via which pass_mgr
  • implement help renderer (--help and --help-brief)
  • add HTTP client wrapper

Phase 2 — Secrets / Mode Behavior

  • implement padded-cell mode flag suppression
  • implement manual mode required credential flags
  • implement normal token resolution rules
  • implement account-manager token resolution rules
  • enforce exact failure messages

Phase 3 — Config + Core Commands

  • hf version
  • hf health
  • hf config --url
  • hf config --acc-mgr-token

Phase 4 — User / Role / Project Baseline

  • hf user create
  • hf user list
  • hf user get
  • hf user update
  • hf user activate
  • hf user deactivate
  • hf user delete
  • hf role list
  • hf role get
  • hf project list
  • hf project get

Phase 5 — Task / Milestone / Propose / Monitor

  • task commands
  • milestone commands
  • propose commands
  • monitor commands
  • meeting commands
  • support commands

Phase 6 — Hardening

  • tests for config-path behavior
  • tests for mode switching (pass_mgr present / absent)
  • tests for exact stderr messages
  • tests for help and help-brief rendering
  • tests for permission-aware help visibility
  • binary packaging / release pipeline

Non-Goals (for now)

  • do not directly port the old Python CLI architecture
  • do not add a separate auth command group
  • do not store normal auth token in .hf-config.json
  • do not expose admin role assignment through hf user create
  • do not broaden account-manager beyond account creation in the first design