Background
Organization Projects have a Project-specific base role for organization members: No access, Read, Write, or Admin. ghpmv can migrate explicitly listed user/team collaborators, but the base role is currently omitted, which can materially change target access.
Confirmed API capability (2026-08-19)
The Project base role is browser-only.
- GitHub.com GraphQL
ProjectV2 and Projects-related organization types expose no base-role/base-permission field or mutation.
updateProjectV2Collaborators manages explicit users/teams only; it is not the base role.
- The Projects REST Project schema has no base-role property or write endpoint.
- GitHub documents the setting only through the Project Settings → Manage access UI.
Changing the base role requires Project admin or organization-owner authority. For an existing target, validate the control before the first mutation. For a newly created target, createProjectV2 must run first; immediately afterward, validate and apply the base role before collaborators, items, or other access-sensitive writers. If that validation fails, remove the newly created target through the existing rollback path and fail explicitly.
Implementation scope
- Add a nullable base-role property for organization-owned Project snapshots; user-owned Projects are not applicable.
- Export No access, Read, Write, or Admin from Manage access.
- Add an explicit importer seam that receives the resolved target Project ID/number and
ProjectImportOutcome before fields, collaborators, linked resources, items, and other snapshot writers run. The current BeforeWriteAsync hook is not sufficient for newly created targets because it runs before createProjectV2.
- Validate browser host/login through the existing pre-write hook. Use the new resolved-target seam to validate and apply the writable Base role control before subsequent snapshot writes: before the first mutation for an existing target, or immediately after
createProjectV2 for a newly created target.
- Apply the base role separately from explicit collaborators.
- Preserve target state for legacy/API-only snapshots where the role was not captured.
- Verify the role through browser-assisted verification.
- Keep organization-wide default Project permission and enterprise policy outside this Project-level property.
Test strategy
- Add serialization, compatibility, owner-type, role parsing, preflight, and verifier tests.
- Add deterministic importer orchestration tests proving the resolved-target hook runs before snapshot writers and that a hook failure rolls back only a newly created target.
- Extend collaborator browser logic tests for the Base role control without conflating it with collaborator rows.
- Add Playwright E2E for all four role values, source export, target import, and target drift.
- Do not add Integration tests for the base-role setting because public REST/GraphQL does not expose it.
- Browser tests must use an authorized account, cancellation tokens, and
finally cleanup/restoration.
ghpmv-e2e-validation skill integration
Do not add a separate user-facing scenario selector for this issue. Extend the existing browser-e2e flow with Base-role checkpoints; run the low-privilege branch only when its optional profile is configured.
Extend the existing ghpmv-e2e-validation browser-e2e flow to validate Project Base roles.
- Extend UI fixture setup to configure a deterministic source Base role plus explicit collaborators with different roles.
- Add optional non-secret settings for a lower-privilege browser profile/login. The required negative-test identity is a plain organization member, not an organization owner, not an explicit Project Admin collaborator, and operating against a Project whose Base role is below Admin.
- Teach the skill to run both fresh-target and existing-target happy paths, inspect snapshot role capture, apply the new importer hook, verify the target role, inject drift, and restore to
Match.
- For the negative path, preserve the one-token/one-terminal rules and use a separate browser profile/token only when configured. Existing-target failure must precede mutations; fresh-target failure must prove rollback and absence of a residual Project.
- If the low-privilege profile is unavailable, record the negative branch as Skipped/NotApplicable with its missing prerequisite; never count it as passed.
- Inventory created Projects and access changes, restore shared access before cleanup, and request explicit deletion consent.
- Update fixture/browser logic tests, Browser E2E tests, skill state/settings validation, and cleanup instructions together.
Existing manual E2E flow additions
E2E runtime consolidation: Do not add a standalone feature scenario or repeat the full fixture/export/import/verify/cleanup sequence. Fold fixture setup into the existing fixture step, snapshot assertions into the existing export result, target assertions into the existing import/verify and visual checklist, deliberate drift into the existing negative-test phase, and repair into the single idempotence re-import. Reuse the same snapshot, mappings, and target Project. Add another disposable target or native command only when a distinct code path cannot be proven otherwise; document why and include every added resource in the existing inventory and cleanup.
Extend the existing browser-assisted migration flow in docs/MANUAL_TEST_PLAN.md with authorized happy-path and permission-failure checkpoints:
Happy path
- Configure a source organization Project with a non-default Base role and explicit collaborators whose roles differ from the Base role.
- Run browser-assisted export, import into both a disposable fresh target and a disposable existing target, and run browser-assisted verify.
- Confirm the target Base role matches while explicit collaborator roles remain independent.
- Change the target Base role, rerun verify, and confirm access drift is reported; rerun import and confirm restoration.
Permission failure
- When a second browser profile is available, use a plain organization member who is not an organization owner, is not an explicit Project Admin collaborator, and whose target Project Base role is below Admin. Run against an existing disposable target and confirm failure before mutations.
- Run the fresh-target path and confirm a failure after
createProjectV2 triggers rollback before subsequent writers and leaves no target Project.
- If a lower-privilege profile is unavailable, mark this manual branch skipped with the reason and rely on deterministic orchestration tests; do not mark it passed.
Record browser profile identity, role before/after, collaborator roles, commands, verify output, and rollback evidence. Restore access and delete all disposable targets during cleanup.
Acceptance criteria
References
Background
Organization Projects have a Project-specific base role for organization members: No access, Read, Write, or Admin.
ghpmvcan migrate explicitly listed user/team collaborators, but the base role is currently omitted, which can materially change target access.Confirmed API capability (2026-08-19)
The Project base role is browser-only.
ProjectV2and Projects-related organization types expose no base-role/base-permission field or mutation.updateProjectV2Collaboratorsmanages explicit users/teams only; it is not the base role.Changing the base role requires Project admin or organization-owner authority. For an existing target, validate the control before the first mutation. For a newly created target,
createProjectV2must run first; immediately afterward, validate and apply the base role before collaborators, items, or other access-sensitive writers. If that validation fails, remove the newly created target through the existing rollback path and fail explicitly.Implementation scope
ProjectImportOutcomebefore fields, collaborators, linked resources, items, and other snapshot writers run. The currentBeforeWriteAsynchook is not sufficient for newly created targets because it runs beforecreateProjectV2.createProjectV2for a newly created target.Test strategy
finallycleanup/restoration.ghpmv-e2e-validationskill integrationDo not add a separate user-facing scenario selector for this issue. Extend the existing
browser-e2eflow with Base-role checkpoints; run the low-privilege branch only when its optional profile is configured.Extend the existing
ghpmv-e2e-validationbrowser-e2eflow to validate Project Base roles.Match.Existing manual E2E flow additions
Extend the existing browser-assisted migration flow in
docs/MANUAL_TEST_PLAN.mdwith authorized happy-path and permission-failure checkpoints:Happy path
Permission failure
createProjectV2triggers rollback before subsequent writers and leaves no target Project.Record browser profile identity, role before/after, collaborator roles, commands, verify output, and rollback evidence. Restore access and delete all disposable targets during cleanup.
Acceptance criteria
ghpmv-e2e-validationcan create/configure Base-role fixtures, run fresh/existing paths, validate drift/restoration and deterministic low-privilege failure/rollback when configured, and restore/clean up access safely.docs/MANUAL_TEST_PLAN.mdcovers fresh/existing happy paths, role drift/restoration, explicit-collaborator independence, permission failure/rollback where credentials permit, and cleanup.All four Project base roles round-trip for organization-owned Projects.
User-owned Projects are reported NotApplicable.
Legacy/API-only snapshots do not change the target role.
Explicit collaborator roles remain independent.
Insufficient authority fails before writes to an existing target; for a newly created target it triggers rollback before subsequent migration stages.
Browser-assisted verify detects role drift.
Documentation distinguishes Project base role, explicit collaborators, and organization-wide defaults.
References