Skip to content

Commit fff125d

Browse files
feat: improve ownership interview controls (#363) (#364)
Co-authored-by: Jonathan Weinberg <2151251+jonathanweinberg@users.noreply.github.com>
1 parent 67ae778 commit fff125d

13 files changed

Lines changed: 750 additions & 138 deletions

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ For the fuller explanation, use the [visual field guide](docs/visual-field-guide
3131

3232
For the first real run:
3333

34-
1. Download `ShareSurfer-0.1.0-pre.33.zip` and its SHA256 file from the [current prerelease](https://github.com/jonathanweinberg/ShareSurfer/releases/tag/v0.1.0-pre.33). If that tag is not visible, use the latest published prerelease and substitute its version in the paths below.
35-
2. Extract to `C:\` so the release root is `C:\ShareSurfer-0.1.0-pre.33\`.
34+
1. Download `ShareSurfer-0.1.0-pre.34.zip` and its SHA256 file from the [current prerelease](https://github.com/jonathanweinberg/ShareSurfer/releases/tag/v0.1.0-pre.34). If that tag is not visible, use the latest published prerelease and substitute its version in the paths below.
35+
2. Extract to `C:\` so the release root is `C:\ShareSurfer-0.1.0-pre.34\`.
3636
3. Recursively unblock extracted PowerShell files:
3737

3838
```powershell
39-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
39+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
4040
Get-ChildItem -LiteralPath $releaseRoot -Recurse -File |
4141
Where-Object { $_.Extension -in '.ps1', '.psm1', '.psd1' } |
4242
Unblock-File
@@ -149,7 +149,7 @@ See the [nonpermissive collector to dashboard host workflow](docs/nonpermissive-
149149
Use this compact pattern when the release folder has been copied to a locked-down Windows collector host:
150150

151151
```powershell
152-
$shareSurferRoot = 'C:\ShareSurfer-0.1.0-pre.33'
152+
$shareSurferRoot = 'C:\ShareSurfer-0.1.0-pre.34'
153153
$exportPath = 'C:\ShareSurfer\exports\scan-001'
154154
$handoffPath = 'C:\ShareSurfer\handoff\scan-001.zip'
155155
$inputRoot = 'C:\ShareSurfer\inputs'
@@ -232,7 +232,7 @@ Current screenshots are under [docs/visuals/dashboard-screenshots/2026-06-09-cur
232232

233233
## Pre-1.0 Release Packaging
234234

235-
The first packages are unsigned but fully built. `v0.1.0-pre.33` includes the module, scripts, docs, SHA256 files, release manifest, dependency-age report, and prebuilt dashboard template assets. The manifest records `UnsignedPre1.0`.
235+
The first packages are unsigned but fully built. `v0.1.0-pre.34` includes the module, scripts, docs, SHA256 files, release manifest, dependency-age report, and prebuilt dashboard template assets. The manifest records `UnsignedPre1.0`.
236236

237237
Release identity lives in [release-metadata.json](release-metadata.json). Update that file first when preparing a prerelease; packaging fails closed when the manual version or tag does not match.
238238

docs/admin-ownership-import.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ Enriched rows can add these review fields:
133133

134134
## Step 1: Test The CSV
135135

136-
If `v0.1.0-pre.33` is not visible yet on the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases), use the latest published prerelease and substitute that version in `$releaseRoot`.
136+
If `v0.1.0-pre.34` is not visible yet on the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases), use the latest published prerelease and substitute that version in `$releaseRoot`.
137137

138138
```powershell
139-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
139+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
140140
$sourcePath = 'C:\ShareSurfer\inputs\hr-obs.csv'
141141
142142
Import-Module "$releaseRoot\src\ShareSurfer\ShareSurfer.psd1" -Force
@@ -192,7 +192,13 @@ New-ShareSurferOwnershipMappingProfile `
192192
-Force
193193
```
194194

195-
During interactive mode, press Enter to accept a suggested header, type another header, or type `S` to skip a field.
195+
During interactive mode, ShareSurfer keeps a controls line on screen:
196+
197+
```text
198+
Enter=accept/select | S=skip | B=back | ?=help | Q=quit
199+
```
200+
201+
Press Enter to accept a suggested header, type another header name when you know it, press `S` to deliberately leave that ShareSurfer field blank, or press `B` to go back and fix the previous field. If there is no confident suggestion and the source has fewer than 10 headers, pressing Enter opens a small selector so you can choose the right header with arrow keys where the console supports them, or by number in simpler hosts.
196202

197203
## Step 3: Import A Normalized Ownership CSV
198204

@@ -257,6 +263,17 @@ Join-ShareSurferOwnershipSources `
257263

258264
In the picker, use the numbered folder and file choices to move around and toggle CSVs. The menu also lets you select all CSVs in the current folder, clear selected paths, show selected paths, go up to the parent folder, finish, or quit.
259265

266+
After you choose source CSV files, interactive ownership enrichment asks what each file mostly describes and how much trust to place in it. The prompts use the same `Enter`, `S`, `B`, `?`, and `Q` controls where they apply. Source type choices are written in business terms:
267+
268+
- `Identity`: people or accounts, usually HR or directory-aligned employee data.
269+
- `ObsContext`: OBS/OID, business-unit, or owner clues.
270+
- `ProjectContext`: projects, programs, apps, or WBS codes linked to OBS or owners.
271+
- `PathOwnership`: share, folder, UNC, or path-prefix ownership clues.
272+
- `GroupContext`: security groups linked to owners, OBS, projects, or business units.
273+
- `Mixed`: several kinds of clues or a file whose purpose is not cleanly separated.
274+
275+
Authority choices tell reviewers how strongly to trust the file: `Authoritative` means a trusted source of record, `ReviewerHint` means useful but review-needed, `ContextOnly` means grouping context only, and `Unknown` means the trust level is unclear. `B` lets you return to an earlier source-classification prompt before the definition JSON is saved.
276+
260277
If you already know the exact files, you can still pass them directly:
261278

262279
```powershell

docs/command-recipes.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ This page collects the most common first-run commands in one place. Use it when
55
The examples assume the current quickstart release is unpacked here:
66

77
```text
8-
C:\ShareSurfer-0.1.0-pre.33\
8+
C:\ShareSurfer-0.1.0-pre.34\
99
```
1010

11-
If `v0.1.0-pre.33` is not visible yet on the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases), use the latest published prerelease and substitute that version in every `ShareSurfer-0.1.0-pre.33` path and ZIP name below. The commands also assume Windows PowerShell 5.1 unless a command explicitly says otherwise.
11+
If `v0.1.0-pre.34` is not visible yet on the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases), use the latest published prerelease and substitute that version in every `ShareSurfer-0.1.0-pre.34` path and ZIP name below. The commands also assume Windows PowerShell 5.1 unless a command explicitly says otherwise.
1212

1313
## Start Here
1414

@@ -49,11 +49,11 @@ If `v0.1.0-pre.33` is not visible yet on the [ShareSurfer Releases page](https:/
4949

5050
## Recipe 1: Unpack and Import the Release
5151

52-
Use this on the Windows collector host after downloading `ShareSurfer-0.1.0-pre.33.zip` from the GitHub release on an approved connected workstation. If that checkpoint ZIP is not published yet, download the latest published prerelease ZIP and update `$releaseZip` and `$releaseRoot` to match it.
52+
Use this on the Windows collector host after downloading `ShareSurfer-0.1.0-pre.34.zip` from the GitHub release on an approved connected workstation. If that checkpoint ZIP is not published yet, download the latest published prerelease ZIP and update `$releaseZip` and `$releaseRoot` to match it.
5353

5454
```powershell
55-
$releaseZip = 'C:\Downloads\ShareSurfer-0.1.0-pre.33.zip'
56-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
55+
$releaseZip = 'C:\Downloads\ShareSurfer-0.1.0-pre.34.zip'
56+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
5757
5858
Expand-Archive -LiteralPath $releaseZip -DestinationPath 'C:\' -Force
5959
Get-ChildItem -LiteralPath $releaseRoot -Recurse -File |
@@ -71,7 +71,7 @@ The `Unblock-File` line clears the Windows downloaded-file block from ShareSurfe
7171

7272
Run that manual unblock first for the no-prompt path. If you start `Start-ShareSurfer.ps1` before unblocking, Windows may still ask once for the launcher itself; after you choose **Run once**, the launcher attempts the same recursive unblock before importing ShareSurfer.
7373

74-
Both `Test-Path` commands should return `True`. If either returns `False`, check for a doubled folder such as `C:\ShareSurfer-0.1.0-pre.33\ShareSurfer-0.1.0-pre.33`.
74+
Both `Test-Path` commands should return `True`. If either returns `False`, check for a doubled folder such as `C:\ShareSurfer-0.1.0-pre.34\ShareSurfer-0.1.0-pre.34`.
7575

7676
## Recipe 1A: Generate a Guided Startup Plan
7777

@@ -84,7 +84,7 @@ If `ownership-enrichment.csv` is missing, interactive startup can offer to launc
8484
The easiest release-root launcher is:
8585

8686
```powershell
87-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
87+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
8888
$inputRoot = 'C:\ShareSurfer\inputs'
8989
$exportPath = 'C:\ShareSurfer\exports\finance-001'
9090
@@ -94,7 +94,7 @@ $exportPath = 'C:\ShareSurfer\exports\finance-001'
9494
If you already know the answers and want to generate the same files without prompts, import the module and call the startup command directly:
9595

9696
```powershell
97-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
97+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
9898
$inputRoot = 'C:\ShareSurfer\inputs'
9999
$exportPath = 'C:\ShareSurfer\exports\finance-001'
100100
@@ -172,7 +172,7 @@ If you do not have either file yet, leave it absent. The scan recipes below only
172172
Use this when another team gives you a CSV with useful owner or OBS data but the headers do not match ShareSurfer's expected owner mapping format.
173173

174174
```powershell
175-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
175+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
176176
$sourcePath = 'C:\ShareSurfer\inputs\hr-obs.csv'
177177
$profilePath = 'C:\ShareSurfer\inputs\hr-obs.mapping.json'
178178
$normalizedPath = 'C:\ShareSurfer\inputs\normalized-ownership.csv'
@@ -206,12 +206,12 @@ This recipe creates three reusable files:
206206
- `normalized-ownership.csv`: canonical ownership rows for review.
207207
- `ownership-import-rerun.ps1`: reusable commands to retest the source and regenerate the normalized CSV without repeating the header interview.
208208

209-
If you need ShareSurfer to ask you about each header in the console, add `-Interactive` to `New-ShareSurferOwnershipMappingProfile`. The saved rerun file still uses the profile afterward.
209+
If you need ShareSurfer to ask you about each header in the console, add `-Interactive` to `New-ShareSurferOwnershipMappingProfile`. The saved rerun file still uses the profile afterward. Interactive prompts show `Enter=accept/select | S=skip | B=back | ?=help | Q=quit`; use `B` to fix the previous field, `S` to intentionally leave a ShareSurfer field blank, and `?` for a reminder. When there is no suggestion and the source has fewer than 10 headers, Enter opens a small selector with arrow-key support where available and numbered fallback everywhere else.
210210

211211
To gather AD data from an HR or OBS file before scanning, create an enrichment CSV. ShareSurfer uses employee ID or employee number values from the source CSV to look up matching AD accounts when `-AdLookupMode Auto` or `ActiveDirectory` can read the directory. It fills available account, mail, title, office, manager, and OBS fields, then writes a local CSV that travels with the scan evidence.
212212

213213
```powershell
214-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
214+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
215215
$inputRoot = 'C:\ShareSurfer\inputs'
216216
$ownershipEnrichmentPath = Join-Path $inputRoot 'ownership-enrichment.csv'
217217
$ownershipDefinitionPath = Join-Path $inputRoot 'ownership-import.definition.json'
@@ -291,7 +291,7 @@ For more detail, see the [admin ownership import guide](admin-ownership-import.m
291291
Use this when you already know the share path and want a first reviewable export.
292292

293293
```powershell
294-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
294+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
295295
$exportPath = 'C:\ShareSurfer\exports\finance-001'
296296
$ownerMappingPath = 'C:\ShareSurfer\inputs\owner-mapping.csv'
297297
$ownershipEnrichmentPath = 'C:\ShareSurfer\inputs\ownership-enrichment.csv'
@@ -332,7 +332,7 @@ Use this recipe first if you are new to the tool. It can still record partial-da
332332
Use this when you know the Windows file server and share name and want ShareSurfer to collect share metadata.
333333

334334
```powershell
335-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
335+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
336336
$exportPath = 'C:\ShareSurfer\exports\finance-001'
337337
338338
Import-Module "$releaseRoot\src\ShareSurfer\ShareSurfer.psd1" -Force
@@ -354,7 +354,7 @@ Use `-IncludeFiles` only when file-level rows matter for the review. Large share
354354
Use this when a Windows SMB target is reachable but default remote CIM or SMB cmdlets cannot prove share metadata cleanly.
355355

356356
```powershell
357-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
357+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
358358
$exportPath = 'C:\ShareSurfer\exports\finance-native-001'
359359
360360
Import-Module "$releaseRoot\src\ShareSurfer\ShareSurfer.psd1" -Force
@@ -379,7 +379,7 @@ When `NetShareGetInfo` returns a path like `C:\Public\Share` for a remote target
379379
Use this when ShareSurfer can reach a share but `share_permissions.csv` is empty, `shares.csv` says `PartialData=True`, or `collection_errors.csv` shows share-permission or native security descriptor failures. This goes past "is the port open" and records each share-permission proof attempt.
380380

381381
```powershell
382-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
382+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
383383
$diagnosticPath = 'C:\ShareSurfer\diagnostics\finance-share-permissions'
384384
385385
Import-Module "$releaseRoot\src\ShareSurfer\ShareSurfer.psd1" -Force
@@ -403,7 +403,7 @@ For a support-safe packet, review and share the redacted files under `$diagnosti
403403
Run this after the collector finishes.
404404

405405
```powershell
406-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
406+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
407407
$exportPath = 'C:\ShareSurfer\exports\finance-001'
408408
409409
Test-ShareSurferExport -ExportPath $exportPath
@@ -430,7 +430,7 @@ Before owner signoff, open `evidence_confidence.csv` or the dashboard Scan Confi
430430
Use this after a scan has produced `owner_review_packets.csv` and `related_data_areas.csv`. The draft files are plain CSVs that can be edited in Excel, reviewed in a meeting, and imported back into the export folder before rebuilding the report or standalone dashboard.
431431

432432
```powershell
433-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
433+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
434434
$exportPath = 'C:\ShareSurfer\exports\finance-001'
435435
$decisionPath = 'C:\ShareSurfer\reviews\finance-001'
436436
$decisionRerunPath = Join-Path $decisionPath 'review-decisions-rerun.ps1'

docs/first-run-guide.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ If report or command terms are unfamiliar, keep the [glossary](glossary.md) open
88

99
For a first useful scan:
1010

11-
1. Extract the current `v0.1.0-pre.33` release ZIP to `C:\`. If that checkpoint tag is not visible on the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases) yet, use the latest published prerelease and substitute that version in the paths below.
12-
2. Use `C:\ShareSurfer-0.1.0-pre.33\` as `$releaseRoot`, or replace the version folder with the published prerelease you actually extracted.
11+
1. Extract the current `v0.1.0-pre.34` release ZIP to `C:\`. If that checkpoint tag is not visible on the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases) yet, use the latest published prerelease and substitute that version in the paths below.
12+
2. Use `C:\ShareSurfer-0.1.0-pre.34\` as `$releaseRoot`, or replace the version folder with the published prerelease you actually extracted.
1313
3. Run the recursive `Unblock-File` command in Step 1 before importing the module.
1414
4. Pick one known share and the correct `-ObsAttribute`.
1515
5. Recommended: run `Start-ShareSurfer.ps1` or `Start-ShareSurferStartup` to generate a reusable first-run JSON config, plan, and rerun script.
@@ -92,17 +92,17 @@ $PSVersionTable.PSVersion
9292

9393
The major version should be `5`.
9494

95-
If you are using the `v0.1.0-pre.33` release ZIP, extract it to `C:\`. If that checkpoint tag is not visible yet, use the latest published prerelease and substitute that version in the paths below. The extracted release root should be:
95+
If you are using the `v0.1.0-pre.34` release ZIP, extract it to `C:\`. If that checkpoint tag is not visible yet, use the latest published prerelease and substitute that version in the paths below. The extracted release root should be:
9696

9797
```text
98-
C:\ShareSurfer-0.1.0-pre.33\
98+
C:\ShareSurfer-0.1.0-pre.34\
9999
```
100100

101-
If Windows Explorer suggests extracting to `C:\ShareSurfer-0.1.0-pre.33`, change the destination to `C:\` so you do not end up with a doubled nested folder. From PowerShell:
101+
If Windows Explorer suggests extracting to `C:\ShareSurfer-0.1.0-pre.34`, change the destination to `C:\` so you do not end up with a doubled nested folder. From PowerShell:
102102

103103
```powershell
104-
$releaseZip = 'C:\Downloads\ShareSurfer-0.1.0-pre.33.zip'
105-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
104+
$releaseZip = 'C:\Downloads\ShareSurfer-0.1.0-pre.34.zip'
105+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
106106
107107
Expand-Archive -LiteralPath $releaseZip -DestinationPath 'C:\' -Force
108108
Get-ChildItem -LiteralPath $releaseRoot -Recurse -File |
@@ -716,12 +716,12 @@ For the longer version, see the [nonpermissive collector to dashboard host workf
716716

717717
## Optional: Generate the Standalone Dashboard
718718

719-
The legacy `report.html` remains the safest default report because it is generated directly by the PowerShell module. The v0.1.0-pre.33 release package from the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases), or the latest published prerelease while waiting for that checkpoint tag to appear, also includes prebuilt standalone dashboard template assets for richer novice-admin and business-owner review.
719+
The legacy `report.html` remains the safest default report because it is generated directly by the PowerShell module. The v0.1.0-pre.34 release package from the [ShareSurfer Releases page](https://github.com/jonathanweinberg/ShareSurfer/releases), or the latest published prerelease while waiting for that checkpoint tag to appear, also includes prebuilt standalone dashboard template assets for richer novice-admin and business-owner review.
720720

721721
If you are using the release ZIP, you do not need Node, npm, Vite, a development server, or internet access to package the dashboard. Run the packager from Windows PowerShell 5.1 and point it at the extracted release root:
722722

723723
```powershell
724-
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.33'
724+
$releaseRoot = 'C:\ShareSurfer-0.1.0-pre.34'
725725
726726
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "$releaseRoot\scripts\New-ShareSurferStandaloneDashboard.ps1" `
727727
-ExportPath $exportPath `

0 commit comments

Comments
 (0)