View all documentations

Team Members Configuration

Wizard uses a team members list to map GitHub users to personal HR repositories, track onboarding dates, and enforce PR time tracking rules.

File Location

The canonical file lives in the holdex/hr-internal repository (HR access only).

For production deployments, the file is fetched at build time via the TEAM_MEMBERS_SOURCE environment variable and bundled into the server — it is never committed to this repository.

For local development and preview deployments, TEAM_MEMBERS_SOURCE can be left unset. Wizard then reads config/team-members.json from your working tree. That file is gitignored and not in the repository — copy config/team-members.json.example to config/team-members.json to get started locally.

@holdex member onboard opens a PR against holdex/hr-internal automatically, adding the new member's entry once the HR issue is created, and requests a review from whoever ran the command. The PR body links back to the issue the command was run from, so the reviewer has the original context. Updates to an existing member (agreement URL, isManager, corrections, and anything else not set at onboarding time) are still made by hand-editing the file in holdex/hr-internal. Changes take effect on the next production deployment.

File Format

The file is a JSON object with an hr_team key and a members array. Each entry in members follows the structure documented in config/team-members.json.example:

{
  "hr_team": "org/hr-admins",
  "members": [
    {
      "repo": "org/hr-member-firstname-lastname",
      "username": "github-username",
      "issue": 1,
      "salaryIssue": 2,
      "agreement": "https://github.com/org/hr-member-firstname-lastname/blob/main/AGREEMENT.md",
      "startDate": "2024-01-01",
      "skipNoPrMergeReminder": false,
      "requiresTimeSubmission": true,
      "isManager": false,
      "billingManager": false,
      "isExternal": false
    }
  ]
}

The legacy flat-array shape (just the members list, no hr_team) is still accepted for backward compatibility.

Top-Level Fields

Field Required Description
hr_team No GitHub team in org/slug format, tagged on monthly invoice comments for visibility.
members Yes Array of team member entries, documented below.

Member Fields

Field Required Description
repo Yes Personal HR repository in owner/repo format.
username Yes GitHub login for the team member.
issue Yes Issue number of the member's main HR issue in their HR repo.
salaryIssue No Issue number of the HR: Salary sub-issue, if created.
agreement No URL to the member's agreement document.
startDate No Agreement signing date (YYYY-MM-DD). Used for leave accrual when leave.yaml is missing.
skipNoPrMergeReminder No When true, skips the "no PRs merged yesterday" message for this member. Defaults to false. The old keys skipDailyPrReminder and skipDailyReminder are still accepted as deprecated aliases. The upcoming-leave notice is unaffected and always fires, since it's a team-coordination signal, not a nag tied to PR-merge pay.
requiresTimeSubmission No When true, the member must submit PR time even if their organization is whitelisted. See Whitelist.
isManager No When true, promotes the member to product-owner responsibilities (Goals, leave approval, restricted commands where applicable). Defaults to false.
billingManager No When true, grants access to view all contractors' invoices and team-wide Cost Breakdown reports (/stats/costs). All team members can access /stats/costs for their own data only. isManager does not grant billing access on its own. Defaults to false.
isExternal No When true, this member has no Holdex agreement and is not paid by Holdex in any form (hourly, retainer, or commission): they're listed here only for delivery-team visibility, e.g. a client-side collaborator. Excluded from monthly billing (see Monthly Billing). Defaults to false.

Monthly Billing and isExternal

Members with isExternal: true are skipped before the monthly billing task runs for them, so no HR: Salary sub-issue is created and they never appear in a billing run's output. This is separate from profile.yaml's engagement_mode, which controls billing cadence for members Holdex does pay (retainer vs employee); isExternal controls whether Holdex has a payment relationship with the member at all.

  • Mandatory users referenced in Whitelist are defined here via requiresTimeSubmission.
  • Leave accrual uses startDate when a member's leave.yaml is not yet present.
  • HR sub-issues (daily reminders, bug reports, salary) are created against the repo and issue fields.
  • hr_team is read by the monthly billing task to tag a team on invoice comments.
  • billingManager members can run on-demand cost allocation reports for any contributor or the whole team; see Cost Breakdown. All team members can run reports for their own data.