docs(v1.2): complete project research — stack, features, architecture, pitfalls, summary
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+210
-266
@@ -1,362 +1,306 @@
|
||||
# Domain Pitfalls
|
||||
# Pitfalls Research
|
||||
|
||||
**Domain:** rclone config generator / PowerShell deployment wizard (Windows/Intune/RMM)
|
||||
**Researched:** 2026-03-26
|
||||
**Confidence:** HIGH (Intune/PowerShell — verified against official Microsoft docs), MEDIUM (rclone-specific — based on format spec knowledge plus training data; rclone docs were inaccessible during research)
|
||||
**Domain:** UI polish overhaul -- Material Design 3, dark mode, accent colors added to existing Tailwind v4 + React wizard app
|
||||
**Researched:** 2026-03-31
|
||||
**Confidence:** HIGH (based on codebase analysis + verified Tailwind v4 docs + community patterns)
|
||||
|
||||
---
|
||||
|
||||
## Critical Pitfalls
|
||||
|
||||
Mistakes that cause the generated script/config to silently fail or require a full rewrite.
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 1: rclone config deployed to wrong path under SYSTEM context
|
||||
### Pitfall 1: Tailwind v4 Dark Mode Requires CSS-First Config, Not tailwind.config.js
|
||||
|
||||
**What goes wrong:**
|
||||
When Intune deploys a PowerShell script with "Run as SYSTEM" (the `No` logged-on-credentials option), the script runs as `NT AUTHORITY\SYSTEM`. The default rclone config location resolves from the SYSTEM user's `%APPDATA%`, which is `C:\Windows\system32\config\systemprofile\AppData\Roaming\rclone\rclone.conf`. This path is not readable by the end user who will later run rclone interactively. The config is deposited silently with no error, but rclone launched by the user finds no config.
|
||||
Developers reach for `tailwind.config.js` with `darkMode: 'class'` which does not exist in Tailwind v4. The app currently has only `@import "tailwindcss";` in `index.css` with no config file at all. Using v3 dark mode patterns produces zero effect and wastes debugging time.
|
||||
|
||||
**Why it happens:**
|
||||
rclone resolves config location from environment variables at runtime. Under SYSTEM, `%APPDATA%` and `%USERPROFILE%` expand to the SYSTEM profile paths, not any individual user's profile. Developers test locally as themselves and never hit this path.
|
||||
Most tutorials and Stack Overflow answers still reference Tailwind v3 syntax. Tailwind v4 moved to a fully CSS-first configuration model. The `darkMode` config key is gone.
|
||||
|
||||
**Consequences:**
|
||||
- rclone runs with no configuration; all sync commands fail with "no remote" error
|
||||
- Hard to debug because the config file exists on disk — just in the wrong place
|
||||
- If the wizard generates a hardcoded `%APPDATA%` path string in the script, that string is evaluated at deployment time (SYSTEM), not at user runtime
|
||||
**How to avoid:**
|
||||
Add the `@custom-variant` directive in `index.css` for class-based toggling:
|
||||
```css
|
||||
@import "tailwindcss";
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
```
|
||||
This enables manual toggle via a `.dark` class on `<html>`. The `:where()` wrapper keeps specificity at zero, preventing cascade conflicts. Verified against [Tailwind v4 dark mode docs](https://tailwindcss.com/docs/dark-mode).
|
||||
|
||||
**Prevention:**
|
||||
- The generated script must write the config to a machine-wide path such as `C:\ProgramData\rclone\rclone.conf` and then invoke rclone with `--config "C:\ProgramData\rclone\rclone.conf"` (or set `RCLONE_CONFIG` env var).
|
||||
- Alternatively: write to each user's profile by running in user context — but SYSTEM context is common for silently deploying software.
|
||||
- The wizard should make the config destination path explicit and let the IT admin choose: machine-wide vs. user-profile. Never default to a bare `%APPDATA%` expansion in a SYSTEM-context script.
|
||||
**Warning signs:**
|
||||
- `dark:` prefixed classes have no visible effect
|
||||
- Dark mode only responds to OS preference, not the toggle button
|
||||
|
||||
**Detection:**
|
||||
- Config exists at SYSTEM profile path but rclone launched by user says "no remote configured"
|
||||
- Check `rclone config file` — it will show the wrong path
|
||||
|
||||
**Phase relevance:** Phase generating the PowerShell script (any phase touching script output)
|
||||
**Phase to address:**
|
||||
Phase 1 (Theme Foundation) -- this must be the very first CSS change before any `dark:` classes are added to components.
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 2: Intune PowerShell scripts are size-limited to 200 KB (ASCII)
|
||||
### Pitfall 2: Hardcoded Color Values Across 73 className Usages
|
||||
|
||||
**What goes wrong:**
|
||||
Microsoft Intune enforces a hard 200 KB (ASCII) size limit on uploaded PowerShell scripts. Scripts that embed a large rclone installer binary (base64-encoded), or that inline multiple large config payloads, will be rejected at upload time.
|
||||
The codebase has 73 `className=` usages with hardcoded Tailwind color classes (`text-gray-700`, `border-gray-300`, `focus:ring-blue-300`, `text-red-500`, `bg-gray-50`, etc.). Adding dark mode by appending a `dark:` counterpart to every single one creates unreadable className strings and guarantees missed spots -- invisible text, invisible borders, or unreadable error messages against dark backgrounds.
|
||||
|
||||
**Why it happens:**
|
||||
IT developers prototype a "self-contained" script that downloads rclone, unpacks it, writes the config, and sets up a scheduled task — all in one file. Base64-encoding a ~50 MB rclone binary produces a ~67 MB string. Even base64-encoding a 400 KB installer produces a 550 KB string, well over the limit.
|
||||
When building light-mode-only, hardcoded color classes are natural. The cost is deferred until dark mode arrives. Developers add `dark:` to the visible components and miss the less-obvious ones (help text, error messages, placeholders, disabled states).
|
||||
|
||||
**Consequences:**
|
||||
- Script upload fails; IT admin gets a non-obvious error in Intune
|
||||
- Workaround requires restructuring the entire script delivery approach
|
||||
**How to avoid:**
|
||||
Define semantic CSS custom properties (design tokens) mapped to Tailwind's `@theme` directive:
|
||||
```css
|
||||
@theme {
|
||||
--color-surface: #ffffff;
|
||||
--color-on-surface: #1a1a1a;
|
||||
--color-primary: #2563eb;
|
||||
--color-error: #dc2626;
|
||||
}
|
||||
```
|
||||
Then use `bg-surface`, `text-on-surface` throughout components. Dark mode changes the token values once (on `.dark`), not every component. This is the Material Design 3 approach (surface, on-surface, primary, on-primary, etc.).
|
||||
|
||||
**Prevention:**
|
||||
- The wizard must never embed rclone binary content into the generated script
|
||||
- The rclone installation step must use a network download (e.g., `Invoke-WebRequest` from the rclone GitHub releases API or a corporate file share URL) or reference a Win32 app deployment separately
|
||||
- Clearly surface this constraint in the wizard: "rclone binary will be downloaded from [URL] at deployment time" — and let the admin specify an internal mirror if internet access is restricted on endpoints
|
||||
**Warning signs:**
|
||||
- `dark:` classes appearing in JSX alongside light classes, creating 100+ character className strings
|
||||
- Text disappearing on dark backgrounds during manual testing
|
||||
- Error messages (`text-red-600`) becoming unreadable against dark backgrounds
|
||||
|
||||
**Detection:**
|
||||
- Intune admin center shows upload error "Script size exceeds limit"
|
||||
- Script file is visibly large before upload
|
||||
|
||||
**Phase relevance:** Phase implementing the rclone-install option in script generation
|
||||
**Phase to address:**
|
||||
Phase 1 (Theme Foundation) defines tokens. Phase 2 (Component Overhaul) replaces hardcoded colors with token references.
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 3: PowerShell script encoding mismatch causes silent config corruption
|
||||
### Pitfall 3: Dark Mode Color Contrast Failures (WCAG AA)
|
||||
|
||||
**What goes wrong:**
|
||||
The generated PowerShell script writes the rclone config file to disk using `Set-Content` or `Out-File`. The default encoding in Windows PowerShell 5.1 is UTF-16 LE with BOM for `Out-File`, and varies for `Set-Content` (system codepage/ANSI on PS 5.1, UTF-8 no-BOM on PS 7+). rclone expects its config file in UTF-8. A config with a UTF-16 BOM or ANSI-encoded special characters (common in storage keys) will be misread, causing authentication failures.
|
||||
Text that passes 4.5:1 contrast in light mode fails in dark mode. The most common failures: gray help text on dark gray backgrounds, red error text on dark surfaces, blue links on dark blue-gray backgrounds. The current app uses `text-gray-500` for help text and `text-red-600` for errors -- both will fail against typical dark backgrounds.
|
||||
|
||||
**Why it happens:**
|
||||
Developers write `Out-File $configPath` and it works in their test because all values are ASCII. The bug surfaces when a customer has a storage account key or SAS token containing characters that differ between encodings, or when the file has a BOM that confuses rclone's parser.
|
||||
Developers assume inverting colors preserves contrast ratios. They do not. Concrete example from this codebase: `text-gray-500` (#6b7280) on `bg-white` (#ffffff) gives 4.6:1 contrast -- barely passing AA. The same `text-gray-500` on `bg-gray-900` (#111827) gives only 3.5:1 -- failing AA for normal text.
|
||||
|
||||
**Consequences:**
|
||||
- rclone silently reads a corrupt config; authentication fails with opaque errors
|
||||
- Hard to reproduce because it only manifests with certain key contents
|
||||
**How to avoid:**
|
||||
Define separate color values per theme within the token system. In dark mode, help text must use a lighter gray (equivalent of `text-gray-400`), errors must use a lighter red (equivalent of `text-red-400`). Semantic tokens centralize these mappings so each value is defined once. Verify every text/background pair with the browser DevTools accessibility panel or WebAIM contrast checker against WCAG AA 4.5:1 minimum for normal text, 3:1 for large text.
|
||||
|
||||
**Prevention:**
|
||||
- The generated script must always write the config with explicit UTF-8 no-BOM encoding:
|
||||
```powershell
|
||||
[System.IO.File]::WriteAllText($configPath, $configContent, [System.Text.Encoding]::UTF8)
|
||||
```
|
||||
or
|
||||
```powershell
|
||||
Set-Content -Path $configPath -Value $configContent -Encoding UTF8
|
||||
```
|
||||
Note: In PowerShell 5.1, `-Encoding UTF8` writes UTF-8 *with* BOM. Use `[System.IO.File]::WriteAllText` with `new System.Text.UTF8Encoding($false)` to guarantee no BOM.
|
||||
- The wizard's script template must hardcode the correct write method; never leave encoding to PS default
|
||||
**Warning signs:**
|
||||
- Help text feels "hard to read" in dark mode during visual review
|
||||
- Browser DevTools accessibility audit flagging contrast ratios below 4.5:1
|
||||
- Error states visually blending into background colors
|
||||
|
||||
**Detection:**
|
||||
- Open the written config in a hex editor: UTF-16 has `FF FE` as first bytes; UTF-8 BOM has `EF BB BF`
|
||||
- rclone error: "unexpected character at start of file" or authentication failures on otherwise valid credentials
|
||||
|
||||
**Phase relevance:** Any phase producing the PowerShell script template
|
||||
**Phase to address:**
|
||||
Phase 1 (Token Definition) for color values. Phase 2 (Component Overhaul) for application. Each component restyle must include a contrast verification before marking complete.
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 4: rclone config section names collide with rclone reserved names or contain invalid characters
|
||||
### Pitfall 4: Breaking 131 Test Selectors During Component Restyling
|
||||
|
||||
**What goes wrong:**
|
||||
rclone remote names in the config are used on the command line as `remotename:path`. The name becomes part of shell arguments and rclone's internal addressing. Names with spaces, colons, forward slashes, or square brackets break the INI section header (`[remote name]` is valid INI only if the name contains no `]`). Names that match rclone built-in remote types (e.g., naming a remote "local", "union", "memory") cause confusing errors. Names starting with a dash conflict with CLI flag parsing.
|
||||
The test suite uses 131 occurrences of `getByText`, `getByRole`, `getByTestId`, `getByLabelText`, and `queryBy` selectors across 5 test files (App.test.tsx, StepIndicator.test.tsx, ReviewStep.test.tsx, RemoteConfigStep.test.tsx, BackendSelectionStep.test.tsx). Restyling components breaks tests by: changing visible text content, wrapping elements in new containers that alter DOM hierarchy, replacing native elements with styled equivalents (changing roles), or removing/renaming aria attributes.
|
||||
|
||||
**Why it happens:**
|
||||
The wizard lets IT admins freely type a remote name without validation. The name goes into `[user input]` verbatim.
|
||||
UI overhauls touch the same JSX that tests query. Specific examples from this codebase:
|
||||
- `getByText(/Backend/)` in StepIndicator.test.tsx breaks if the label text changes or gets wrapped in a `<span>` that splits the text node
|
||||
- `getAllByRole('button')` breaks if buttons become styled `<a>` tags or `<div>` elements
|
||||
- `screen.findByText('2', { selector: '[data-testid="step"]' })` breaks if data-testid attributes are renamed during refactoring
|
||||
|
||||
**Consequences:**
|
||||
- Config is syntactically broken (rclone fails to parse)
|
||||
- Or config parses but the remote cannot be referenced on the command line
|
||||
- Error messages are cryptic: "Failed to create file system for remotename: didn't find section in config file"
|
||||
**How to avoid:**
|
||||
1. Run the full 159-test suite after every single component change, not in a batch at the end.
|
||||
2. Restyle one component, verify tests, commit. Never batch-restyle all components then fix all tests.
|
||||
3. When restructuring JSX, preserve text content and element roles. A `<button>` must remain a `<button>`.
|
||||
4. If adding wrapper elements, ensure text nodes are not split (e.g., `getByText(/Backend/)` matches a single text node, not text across siblings).
|
||||
|
||||
**Prevention:**
|
||||
- Validate remote names in the wizard UI before generation: allow only `[a-zA-Z0-9_-]`, max ~40 chars, no leading dash
|
||||
- Show a live preview of the section header: `[my-remote]`
|
||||
- Reject reserved-looking names or warn on them
|
||||
**Warning signs:**
|
||||
- More than 3 test failures appearing simultaneously after a restyle
|
||||
- Tests failing with "Unable to find element" errors
|
||||
- `getByRole` queries returning unexpected counts
|
||||
|
||||
**Detection:**
|
||||
- rclone returns "didn't find section in config file" when the name contains special characters
|
||||
- rclone returns parse error when name contains `]`
|
||||
|
||||
**Phase relevance:** Wizard input validation phase; config generation phase
|
||||
**Phase to address:**
|
||||
Every phase -- each component change must include a "159 tests green" gate. This is the single most likely source of rework.
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 5: Secrets embedded in generated scripts are exposed in Intune admin center logs
|
||||
### Pitfall 5: Flash of Unstyled Content (FOUC) on Dark Mode Load
|
||||
|
||||
**What goes wrong:**
|
||||
Intune logs PowerShell script output and stores it in the Azure portal (AgentExecutor.log on endpoint + reporting in Intune admin center). If the generated script echoes the config content or uses `Write-Host` with credential values for debugging, those secrets are persisted in logs accessible to any Intune admin.
|
||||
The app loads with light mode CSS, then JavaScript runs and toggles the `.dark` class, causing a visible white flash. For IT professionals who often use dark OS themes, this flash is jarring and signals low quality.
|
||||
|
||||
**Why it happens:**
|
||||
Developers add debug output during testing ("Writing config: [content]") and forget to remove it. Or error handlers dump the config on failure.
|
||||
React runs after the initial paint. If dark mode preference is stored in `localStorage` and applied via `useEffect` or React state, the first paint is always light mode. The class toggle happens milliseconds later, but the flash is visible.
|
||||
|
||||
**Consequences:**
|
||||
- Storage account keys, SAS tokens, or OAuth secrets appear in Intune reporting
|
||||
- Violates least-privilege and secrets hygiene; potential audit/compliance failure
|
||||
**How to avoid:**
|
||||
Add a synchronous inline `<script>` in the `<head>` of `index.html` (before any CSS or React bundle loads):
|
||||
```html
|
||||
<script>
|
||||
if (localStorage.theme === 'dark' ||
|
||||
(!('theme' in localStorage) &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
</script>
|
||||
```
|
||||
This executes before first paint, preventing any flash. The React toggle component then reads and syncs with the already-applied state.
|
||||
|
||||
**Prevention:**
|
||||
- The wizard's generated script template must never echo credential values
|
||||
- Use a sentinel like `Write-Host "Writing config to $configPath"` (path only, no content)
|
||||
- Add a comment in the generated script: `# Do not add Write-Host or logging for $configContent`
|
||||
- The wizard UI must display a security warning at download time (already planned per PROJECT.md)
|
||||
**Warning signs:**
|
||||
- White flash visible when loading the app with dark mode previously enabled
|
||||
- Users on dark OS themes seeing a brief light flash on every page load
|
||||
|
||||
**Detection:**
|
||||
- Audit the script template for any interpolation of credential variables into strings passed to output cmdlets
|
||||
|
||||
**Phase relevance:** Script template design (early phase); security review before any release
|
||||
**Phase to address:**
|
||||
Phase 1 (Theme Foundation) -- the FOUC prevention script must ship together with the dark mode toggle implementation, not as a later fix.
|
||||
|
||||
---
|
||||
|
||||
## Moderate Pitfalls
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 6: Group Policy overrides PowerShell execution policy set in the script
|
||||
### Pitfall 6: Theme Context Re-renders Causing Full Wizard Re-render
|
||||
|
||||
**What goes wrong:**
|
||||
The generated script attempts to set `Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned` or `Bypass`. In enterprise environments with Group Policy managing `MachinePolicy` or `UserPolicy` execution policy scopes, the script's `Set-ExecutionPolicy` call has no effect — Group Policy always wins. The script appears to succeed (no error from `Set-ExecutionPolicy`) but subsequent script logic may still fail if the endpoint GP enforces `AllSigned` or `Restricted`.
|
||||
Adding a `ThemeContext` that stores `{ theme: 'dark', accentColor: 'blue' }` causes every `useTheme()` consumer to re-render when any theme value changes. Since the app already has a `WizardContext` with `useReducer`, adding another context that triggers re-renders on toggle will cause all 4 wizard steps to re-render, potentially resetting form input focus or scroll position.
|
||||
|
||||
**Why it happens:**
|
||||
Official Microsoft docs confirm: "Set-ExecutionPolicy doesn't override a Group Policy, even if the user preference is more restrictive than the policy." Intune itself bypasses execution policy for its own scripts (IME uses `-ExecutionPolicy Bypass` internally), but any child processes spawned by the script inherit the GP-enforced policy.
|
||||
React Context re-renders every consumer when the provider value changes (referential equality). Tutorials show `<ThemeProvider value={{ theme, setTheme }}>` where a new object is created on every render. Even with `useMemo`, toggling theme changes the value and re-renders all consumers.
|
||||
|
||||
**Consequences:**
|
||||
- Scripts that call `& rclone.exe` or invoke helper `.ps1` files from within the script fail with execution policy errors
|
||||
- Developers test on unmanaged machines and never observe GP interference
|
||||
**How to avoid:**
|
||||
Do NOT store theme in React Context. Apply the theme via the `.dark` CSS class on `<html>` element and CSS custom properties. Theme toggling becomes a DOM class toggle (zero React re-renders). Store the toggle state in a small component-local state that only the toggle button uses:
|
||||
```tsx
|
||||
function ThemeToggle() {
|
||||
const [isDark, setIsDark] = useState(() =>
|
||||
document.documentElement.classList.contains('dark')
|
||||
);
|
||||
const toggle = () => {
|
||||
document.documentElement.classList.toggle('dark');
|
||||
setIsDark(d => !d);
|
||||
localStorage.theme = isDark ? 'light' : 'dark';
|
||||
};
|
||||
return <button onClick={toggle}>...</button>;
|
||||
}
|
||||
```
|
||||
Only the toggle button re-renders. No context, no provider, no cascade. Accent color works the same way -- set a CSS variable on `<html>`, no React re-render.
|
||||
|
||||
**Prevention:**
|
||||
- The generated script should not attempt to change execution policy
|
||||
- Any sub-scripts should be invoked with `-ExecutionPolicy Bypass` in the powershell.exe call, or avoided entirely (inline everything)
|
||||
- Document this in the wizard's "Intune deployment" output pane
|
||||
**Warning signs:**
|
||||
- Form inputs losing focus when toggling dark mode
|
||||
- Visible flicker across the entire wizard when toggling
|
||||
- React DevTools profiler showing all components re-rendering on theme change
|
||||
|
||||
**Detection:**
|
||||
- `Get-ExecutionPolicy -List` on target machine shows `MachinePolicy = AllSigned`
|
||||
- Script works in test but fails on managed fleet endpoints
|
||||
|
||||
**Phase relevance:** Script generation phase; testing guidance
|
||||
**Phase to address:**
|
||||
Phase 1 (Theme Foundation) -- architecture decision: CSS class approach, not React Context for theming.
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 7: 32-bit vs 64-bit PowerShell host affects path resolution
|
||||
### Pitfall 7: Form Accessibility Regressions During Restyling
|
||||
|
||||
**What goes wrong:**
|
||||
Intune's default is to run scripts in the 32-bit PowerShell host (`Run script in 64-bit PowerShell host = No`). On 64-bit Windows, 32-bit processes use File System Redirector: `System32` resolves to `SysWOW64`, and `%ProgramFiles%` resolves to `%ProgramFiles(x86)%`. If the generated script installs rclone to `$env:ProgramFiles\rclone\` under 32-bit context, the binary lands in `C:\Program Files (x86)\rclone\`, not `C:\Program Files\rclone\`. When the user runs rclone from a 64-bit shell, they look in `Program Files` and find nothing.
|
||||
The current FieldRenderer has proper `<label htmlFor>` and `<input id>` associations, error message display, and tooltip buttons with `aria-label`. During restyling, these connections break: labels get separated from inputs by decorative wrapper divs, error messages lose their visual proximity, or card wrappers introduce unexpected tab stops.
|
||||
|
||||
**Why it happens:**
|
||||
The Intune "Run in 64-bit" option defaults to `No` per Microsoft docs. Developers test in a normal 64-bit PowerShell session.
|
||||
Visual-focused restyling treats JSX as a canvas for layout. Developers restructure DOM for card layouts, add icon containers, or wrap form groups in Material-style "outlined" containers. The label-input-error chain relies on specific DOM relationships. The FieldRenderer currently does NOT use `aria-describedby` for error messages -- this is already noted as v1.1 tech debt. Restyling is the right time to fix this, but also the highest risk time to break what works.
|
||||
|
||||
**Consequences:**
|
||||
- rclone binary installed to wrong Program Files variant
|
||||
- PATH entries or shortcuts point to non-existent location
|
||||
**How to avoid:**
|
||||
1. Fix the `aria-describedby` gap as part of the restyling, not separately. Add `aria-describedby={error ? \`${field.key}-error\` : undefined}` to inputs and `id={\`${field.key}-error\`}` to error paragraphs.
|
||||
2. After restyling each form component, verify: label click focuses the input, error messages are associated with inputs, tab order follows visual order.
|
||||
3. Keep the `<label htmlFor={field.key}>` + `<input id={field.key}>` pattern intact regardless of wrapper changes.
|
||||
|
||||
**Prevention:**
|
||||
- The generated script should use `$env:ProgramW6432` (always the native 64-bit Program Files on 64-bit Windows) or hardcode `C:\Program Files\rclone\`
|
||||
- The wizard UI for Intune output should recommend enabling "Run script in 64-bit PowerShell host" and document why
|
||||
- Alternatively, use `C:\ProgramData\rclone\` which is not subject to WOW64 redirection
|
||||
**Warning signs:**
|
||||
- Clicking a label no longer focuses its input
|
||||
- Tab key skips inputs or gets trapped in decorative elements
|
||||
- Browser form autofill stops working on restyled inputs
|
||||
|
||||
**Detection:**
|
||||
- rclone binary absent from expected path after deployment
|
||||
- `[System.Environment]::Is64BitProcess` returns `False` inside the running script
|
||||
|
||||
**Phase relevance:** Script generation phase; Intune deployment option
|
||||
**Phase to address:**
|
||||
Phase 2 (Component Overhaul) -- every form component restyle must include an accessibility verification step. Resolve the v1.1 aria tech debt item here rather than deferring again.
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 8: OAuth-backed backends require interactive browser flow — incompatible with SYSTEM/headless deployment
|
||||
## Technical Debt Patterns
|
||||
|
||||
**What goes wrong:**
|
||||
rclone backends that use OAuth (OneDrive, Google Drive, Dropbox, Box, etc.) require an interactive browser authorization step to generate the token. The rclone config for these backends includes an `token = {...}` JSON blob. If the IT admin generates a config without pre-populating this token, the deployment script writes a config with no token. When rclone first runs on the endpoint, it attempts an interactive browser flow — which silently fails or hangs in a SYSTEM/headless context.
|
||||
Shortcuts that seem reasonable but create long-term problems.
|
||||
|
||||
**Why it happens:**
|
||||
The wizard generates the config from form inputs. For OAuth backends, the wizard cannot complete the OAuth flow on behalf of the user — there is no rclone running in the browser context to perform `rclone config`. The IT admin might not realize the token needs to be obtained separately on a reference machine.
|
||||
| Shortcut | Immediate Benefit | Long-term Cost | When Acceptable |
|
||||
|----------|-------------------|----------------|-----------------|
|
||||
| Adding `dark:` to every className instead of tokens | Fast, no refactor needed | 73+ locations to maintain, every new component needs dual classes | Never -- token approach costs the same upfront and scales |
|
||||
| Using `!important` to fix specificity issues | Immediate visual fix | Cascading specificity arms race, impossible to override later | Never |
|
||||
| Storing theme only in React state (not localStorage) | Simpler code | Preference lost on refresh, FOUC on every load | Never -- localStorage + inline script is trivial |
|
||||
| Skipping contrast verification "will check later" | Faster shipping | Accessibility failures discovered post-ship, painful to retroactively audit all 73 class locations | Never -- check during each component restyle |
|
||||
| Building a full design system with token categories for every MD3 role | "Complete" spec adherence | Over-engineered for a 4-step wizard with ~10 components; 80% of tokens go unused | Never for this app -- pick the 15-20 tokens that matter |
|
||||
| Copying MD3 token names verbatim (md-sys-color-surface-container-highest) | Matches Google spec exactly | Verbose, unfamiliar to Tailwind developers, poor DX for a small team | Never -- use simplified semantic names (surface, on-surface, primary) |
|
||||
| Adding MUI or another component library for "proper" MD3 | Instant MD3 components | +200KB bundle, specificity wars with Tailwind, two styling systems to maintain | Never for this app -- 10 components do not justify a library |
|
||||
|
||||
**Consequences:**
|
||||
- Deployed rclone silently does nothing or opens a browser on the endpoint
|
||||
- Most prominent with OneDrive; affects any backend requiring `rclone authorize`
|
||||
## Integration Gotchas
|
||||
|
||||
**Prevention:**
|
||||
- For OAuth backends, the wizard must show a prominent notice: "This backend requires an OAuth token. You must run `rclone config` or `rclone authorize` on a reference Windows machine as the target user, then copy the resulting token value into this wizard."
|
||||
- The wizard should provide a dedicated "OAuth token" input field for token-based backends, with instructions for how to extract the token from `rclone config show remotename`
|
||||
- Consider warning against deploying OAuth backends via SYSTEM-context Intune scripts entirely; recommend user-context deployment instead
|
||||
Common mistakes when connecting theme infrastructure to existing systems.
|
||||
|
||||
**Detection:**
|
||||
- Config section for OneDrive/GDrive has no `token =` line
|
||||
- rclone first-run opens a browser on the endpoint or exits with "no token found"
|
||||
| Integration | Common Mistake | Correct Approach |
|
||||
|-------------|----------------|------------------|
|
||||
| react-hook-form + restyled inputs | Wrapping `<input>` in a custom component that breaks `register()` ref forwarding | Use `React.forwardRef` on any custom input wrapper, or keep native `<input>` with Tailwind classes (preferred for this app) |
|
||||
| Zod validation + error display | Moving error `<p>` tags away from their input during restyle, breaking visual association | Keep error message immediately after its input in DOM order; add `aria-describedby` |
|
||||
| WizardContext + theme toggle | Creating a ThemeContext provider that causes WizardProvider consumers to re-render | Theme via CSS class on `<html>` (zero React re-renders), NOT via React context |
|
||||
| CSS hidden auth toggles (AzureAuthToggle / SftpAuthToggle) | Restyling visible state but forgetting the hidden state, breaking `className="hidden"` pattern | Verify both auth toggle states render correctly in both light and dark modes |
|
||||
| StepIndicator inline styles | Replacing `style={{ fontWeight: 'bold' }}` with Tailwind classes but altering text content structure | Replace inline styles with Tailwind classes (`font-bold`, `font-normal`, `text-muted`) while keeping text content strings identical for test compatibility |
|
||||
| BackendCard selection state | Changing selection indicator (e.g., border color) to use tokens but forgetting dark mode variant | Selected card must be visually distinct in both themes; test with all 7 backends |
|
||||
|
||||
**Phase relevance:** Backend-specific configuration phase; wizard backend selection step
|
||||
## Performance Traps
|
||||
|
||||
---
|
||||
| Trap | Symptoms | Prevention | When It Breaks |
|
||||
|------|----------|------------|----------------|
|
||||
| Theme stored in React Context causing re-renders | All 4 wizard steps re-render on every toggle; form focus lost | CSS class on `<html>`, no React context for theme | Immediate on every toggle |
|
||||
| Importing full component library for 10 components | Bundle doubles (+200KB gzipped for MUI) | Build MD3 styles with Tailwind tokens; zero additional dependencies | Immediate -- slower first load |
|
||||
| CSS transition on every property during theme switch | 200ms lag on every element when toggling dark mode | Transition only `background-color` and `color` on body; skip borders/shadows | Noticeable with 50+ DOM elements |
|
||||
| Over-using CSS custom properties on every element | Slow repaints when toggling theme on low-end devices | Define tokens on `:root` / `.dark`, let inheritance cascade naturally | On low-end devices or with 100+ custom properties |
|
||||
|
||||
### Pitfall 9: SAS tokens and storage keys contain characters that need escaping in INI values
|
||||
## UX Pitfalls
|
||||
|
||||
**What goes wrong:**
|
||||
Azure SAS tokens contain `%`, `=`, `&`, and `+` characters. Azure storage keys contain `+` and `/` and end in `==`. In rclone's INI config format, values are read until end-of-line — no quoting needed for most characters — but if the value accidentally contains a line-break (e.g., from copy-paste in a browser field that wraps), the config is truncated silently. If the generated value is also used inside a PowerShell string interpolation (e.g., `"sas_url = $sasToken"`), PowerShell variable substitution can corrupt values containing `$`.
|
||||
| Pitfall | User Impact | Better Approach |
|
||||
|---------|-------------|-----------------|
|
||||
| Dark mode toggle buried in settings | IT pros who want dark mode cannot find it | Visible toggle in app header, immediately accessible |
|
||||
| No system preference detection | User has OS dark mode, app loads light | Default to OS preference via `prefers-color-scheme`, with manual override stored in localStorage |
|
||||
| Accent color picker with unlimited options | Analysis paralysis, clashing colors | 3-5 curated accent colors that all pass contrast checks in both themes |
|
||||
| Theme transition animation on every element | Jarring, slow, distracting on toggle | Subtle 150ms transition on background-color and color on body only |
|
||||
| Dark mode applied but OutputBlock code still light | Inconsistent feel in the most important step (Review/download) | OutputBlock must respect dark mode for generated config and script previews |
|
||||
| Security warning banner lost in dark mode | Users miss the credential security warning before download | Warning must remain high-contrast and prominent (use error/warning token colors) in both modes |
|
||||
|
||||
**Why it happens:**
|
||||
The wizard builds the config as a JavaScript template literal. Storage keys and SAS tokens pasted by users may include trailing newlines or spaces. PowerShell double-quoted strings treat `$` as variable prefix.
|
||||
## "Looks Done But Isn't" Checklist
|
||||
|
||||
**Consequences:**
|
||||
- Truncated SAS token causes authentication failures with opaque Azure storage errors
|
||||
- Corrupted key causes "AuthenticationFailed" from Azure
|
||||
Things that appear complete but are missing critical pieces.
|
||||
|
||||
**Prevention:**
|
||||
- Trim all credential inputs in the wizard before inserting into the config (strip leading/trailing whitespace including `\n`, `\r`)
|
||||
- In the PowerShell script template, use single-quoted strings for the config content (PowerShell single-quoted strings do not interpolate `$`):
|
||||
```powershell
|
||||
$configContent = @'
|
||||
[myremote]
|
||||
type = azureblob
|
||||
account = mystorageaccount
|
||||
key = ABC+xyz==
|
||||
'@
|
||||
```
|
||||
(here-string with single-quote terminator)
|
||||
- Validate that credential inputs do not contain newlines before generating
|
||||
- [ ] **Dark mode select dropdowns:** Browser renders `<option>` elements with OS colors -- white dropdown menus appear on dark backgrounds on some browsers. Verify on Chrome, Firefox, Edge.
|
||||
- [ ] **Dark mode scrollbars:** Light scrollbars on dark backgrounds look broken. Apply `scrollbar-color` CSS property or use `dark` color-scheme.
|
||||
- [ ] **Error text contrast:** `text-red-600` on dark backgrounds has insufficient contrast. Must use lighter red (equivalent of `text-red-400`) in dark mode via tokens.
|
||||
- [ ] **Focus rings in dark mode:** `focus:ring-blue-300` is nearly invisible on dark backgrounds. Must use `focus:ring-blue-500` equivalent in dark mode.
|
||||
- [ ] **Placeholder text in dark mode:** Light gray placeholder text vanishes on dark input backgrounds. Verify placeholder is visible in both modes.
|
||||
- [ ] **Security warning banner:** The credential warning in ReviewStep must remain prominent and high-contrast in dark mode (not just "inverted").
|
||||
- [ ] **Accent color + dark background:** Verify every accent color option still passes WCAG AA 4.5:1 against the dark surface background.
|
||||
- [ ] **BackendCard hover and selected states:** Card states must be visually distinguishable in both modes with all 7 backends.
|
||||
- [ ] **Disabled button contrast:** Disabled buttons using lower opacity reduce contrast further on dark backgrounds. Use distinct disabled token colors instead of opacity.
|
||||
- [ ] **PasswordField show/hide toggle:** The eye icon/button must be visible in both themes.
|
||||
- [ ] **Tooltip info boxes:** The `bg-blue-50 border-blue-200 text-blue-700` tooltip in FieldRenderer needs a dark mode equivalent that maintains readability.
|
||||
|
||||
**Detection:**
|
||||
- Config file, when opened, shows a truncated key value
|
||||
- rclone error: "failed to parse config file" or Azure "AuthenticationFailed"
|
||||
## Recovery Strategies
|
||||
|
||||
**Phase relevance:** Config generation logic (core phase)
|
||||
When pitfalls occur despite prevention, how to recover.
|
||||
|
||||
---
|
||||
| Pitfall | Recovery Cost | Recovery Steps |
|
||||
|---------|---------------|----------------|
|
||||
| Hardcoded colors everywhere (no tokens) | MEDIUM | Extract to CSS variables in one pass, then find-replace all 73 className usages. ~2 hours for this codebase. |
|
||||
| Test suite broken by batch restyle | LOW-MEDIUM | `git stash` the batch change, restyle one component at a time verifying tests between each. |
|
||||
| FOUC on dark mode | LOW | Add 5-line inline script to `index.html <head>`. 10-minute fix. |
|
||||
| Specificity conflicts from component library | HIGH | Remove component library, rebuild styles with Tailwind. Prevention is far cheaper than recovery. |
|
||||
| Accessibility regressions in forms | MEDIUM | Audit with browser accessibility tools, fix label/input/aria associations. Harder to find than to fix. |
|
||||
| Dark mode contrast failures | LOW-MEDIUM | With centralized tokens: update token values once. Without tokens: hunt through all 73 className usages. |
|
||||
| Theme context re-renders | LOW | Remove ThemeContext, move to CSS class approach. ~30 minutes if caught early. |
|
||||
|
||||
### Pitfall 10: Windows path length limit (MAX_PATH = 260) breaks rclone operations on deep directory trees
|
||||
## Pitfall-to-Phase Mapping
|
||||
|
||||
**What goes wrong:**
|
||||
On Windows versions before Windows 10 1607, and on any Windows where the Long Path registry key is not set, paths exceeding 260 characters cause rclone operations to fail silently or with cryptic I/O errors. rclone syncing deep SharePoint or OneDrive folder trees commonly hits this. The deployment script may also fail if it writes files to paths that are too long (e.g., user profile paths with long usernames inside long corporate folder structures).
|
||||
|
||||
**Why it happens:**
|
||||
Windows enforces MAX_PATH = 260 by default per `kernel32.dll`. IT admins don't control the endpoint's registry setting. The wizard generates scripts without path-length guards.
|
||||
|
||||
**Consequences:**
|
||||
- rclone skips or errors on files with long paths
|
||||
- `New-Item` or `Set-Content` in the PowerShell script itself can fail if the config destination path is long
|
||||
|
||||
**Prevention:**
|
||||
- The wizard should recommend using `C:\ProgramData\rclone\` (short path) for config and binary placement, not user-profile paths
|
||||
- Generated scripts should include a check and optionally enable long paths:
|
||||
```powershell
|
||||
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1
|
||||
```
|
||||
(requires admin rights; typically available in SYSTEM context)
|
||||
- Document the limitation in the wizard output pane for Intune deployments
|
||||
|
||||
**Detection:**
|
||||
- rclone logs show `ERROR: ... path too long`
|
||||
- PowerShell script itself fails with "The specified path, file name, or both are too long"
|
||||
|
||||
**Phase relevance:** Script generation; deployment documentation phase
|
||||
|
||||
---
|
||||
|
||||
## Minor Pitfalls
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 11: Intune script runs once per device; config changes don't re-deploy unless script is modified
|
||||
|
||||
**What goes wrong:**
|
||||
Intune only re-runs a PowerShell script if the script content changes or is reassigned. If the IT admin generates a new config (different credentials, different remote name) and wants to update the deployed config, they must upload a new version of the script to Intune. If they upload the exact same script bytes with only a comment changed, the re-run is triggered. But if they don't know this, they think re-assigning the unchanged script will update endpoints — it won't.
|
||||
|
||||
**Prevention:**
|
||||
- Document this in the wizard output: "To update config on endpoints, modify and re-upload the script (e.g., bump a version comment) to trigger Intune re-execution."
|
||||
- Consider auto-inserting a `# Generated: [timestamp]` comment in each script so re-generated scripts always differ
|
||||
|
||||
**Phase relevance:** Documentation/UX phase
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 12: rclone binary download URL in the script becomes stale
|
||||
|
||||
**What goes wrong:**
|
||||
The generated script contains a hardcoded rclone download URL (e.g., `https://downloads.rclone.org/rclone-current-windows-amd64.zip`). rclone uses the filename `rclone-current-*` as a redirect alias. This URL is stable, but if the wizard hardcodes a specific version URL (e.g., `v1.68.0`) to ensure repeatability, that version URL remains functional but the binary may have known issues. If the wizard uses `current`, the binary silently upgrades, potentially introducing breaking changes.
|
||||
|
||||
**Prevention:**
|
||||
- Use the `rclone-current-windows-amd64.zip` alias for the default path (always latest stable)
|
||||
- Allow an override field for IT admins who want to pin a version
|
||||
- Add a comment in the generated script stating the resolved version strategy
|
||||
|
||||
**Phase relevance:** Script generation (rclone install option)
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 13: Generated config has Windows-style line endings that cause issues on cross-platform rclone use
|
||||
|
||||
**What goes wrong:**
|
||||
JavaScript running in a browser on Windows may produce `\r\n` line endings when building the config string (less likely with modern JS but possible with string concatenation involving platform newlines). rclone's INI parser handles `\r\n` correctly on Windows, but if the config is later copied to a Linux/macOS system, the `\r` characters appear in values.
|
||||
|
||||
**Prevention:**
|
||||
- Explicitly normalize line endings to `\n` in the config generation logic before download
|
||||
- Use `content.replace(/\r\n/g, '\n').replace(/\r/g, '\n')` before creating the Blob for download
|
||||
|
||||
**Phase relevance:** Config generation (frontend logic)
|
||||
|
||||
---
|
||||
|
||||
## Phase-Specific Warnings
|
||||
|
||||
| Phase Topic | Likely Pitfall | Mitigation |
|
||||
|-------------|---------------|------------|
|
||||
| Script template design | SYSTEM context config path mismatch (Pitfall 1) | Use machine-wide path; document context options |
|
||||
| rclone install option | 200 KB Intune script size limit (Pitfall 2) | Download-only; never embed binary |
|
||||
| Script file write logic | PowerShell encoding writes UTF-16 BOM (Pitfall 3) | Use `[System.IO.File]::WriteAllText` with explicit UTF-8 no-BOM |
|
||||
| Remote name input field | Invalid characters in section name (Pitfall 4) | Validate `[a-zA-Z0-9_-]` in UI before generation |
|
||||
| Debug/error output in script | Secrets exposed in Intune logs (Pitfall 5) | No credential interpolation in output cmdlets |
|
||||
| Execution policy in script | GP overrides any Set-ExecutionPolicy call (Pitfall 6) | Do not set policy; use `-ExecutionPolicy Bypass` on sub-processes |
|
||||
| Intune script options | 32-bit host path redirection (Pitfall 7) | Use `$env:ProgramW6432` or `C:\ProgramData\rclone\` |
|
||||
| OAuth backend config | Headless OAuth flow impossible (Pitfall 8) | Require pre-obtained token; prominent wizard warning |
|
||||
| Credential input handling | SAS/key corruption via whitespace or `$` (Pitfall 9) | Trim inputs; single-quoted PowerShell here-strings |
|
||||
| Config/binary placement | MAX_PATH exceeded on deep trees (Pitfall 10) | Short machine-wide paths; optionally enable long paths |
|
||||
| Re-deployment UX | Intune won't re-run identical script (Pitfall 11) | Auto-insert timestamp comment; document update flow |
|
||||
| rclone download URL | Pinned URL goes stale (Pitfall 12) | Default to `rclone-current`; allow version override |
|
||||
| Config string generation | Windows CRLF in config file (Pitfall 13) | Normalize to LF before Blob creation |
|
||||
|
||||
---
|
||||
| Pitfall | Prevention Phase | Verification |
|
||||
|---------|------------------|--------------|
|
||||
| Tailwind v4 dark mode config (P1) | Phase 1: Theme Foundation | `dark:bg-gray-900` toggles correctly via `.dark` class on `<html>` |
|
||||
| Hardcoded colors (P2) | Phase 1 (Tokens) + Phase 2 (Overhaul) | Zero hardcoded Tailwind color classes remain in component JSX |
|
||||
| Dark mode contrast failures (P3) | Phase 2: Component Overhaul | Every text/background pair checked, all pass WCAG AA 4.5:1 |
|
||||
| Breaking test selectors (P4) | Every phase | All 159 tests pass after each individual component restyle |
|
||||
| FOUC (P5) | Phase 1: Theme Foundation | Load app with `localStorage.theme = 'dark'`, verify no white flash |
|
||||
| Theme context re-renders (P6) | Phase 1: Architecture Decision | Theme toggle causes zero React re-renders outside the toggle button itself |
|
||||
| Form accessibility regressions (P7) | Phase 2: Component Overhaul | Label-input associations verified, `aria-describedby` added for all error messages |
|
||||
| CSS specificity conflicts | Phase 1: Architecture Decision | Decision documented: no component library, Tailwind-only approach |
|
||||
| Over-engineering design system | Phase 1: Token Definition | Token count stays under 20 semantic colors; no unused token categories |
|
||||
|
||||
## Sources
|
||||
|
||||
- Microsoft Learn — PowerShell scripts in Intune (updated 2025-10-02): https://learn.microsoft.com/en-us/intune/intune-service/apps/powershell-scripts
|
||||
- Microsoft Learn — Intune Management Extension (updated 2026-03-17): https://learn.microsoft.com/en-us/intune/intune-service/apps/intune-management-extension
|
||||
- Microsoft Learn — Set-ExecutionPolicy reference (updated 2025-04-15): https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy
|
||||
- Microsoft Learn — Naming Files, Paths, and Namespaces (Win32): https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
|
||||
- Microsoft Learn — Code Page Identifiers: https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
|
||||
- rclone config format and Windows behavior: training data (MEDIUM confidence; rclone official docs were inaccessible during research session — verify against https://rclone.org/docs/ before finalizing)
|
||||
- [Tailwind CSS v4 Dark Mode docs](https://tailwindcss.com/docs/dark-mode) -- official, verified (HIGH confidence)
|
||||
- [Tailwind v4 upgrade discussion #16517](https://github.com/tailwindlabs/tailwindcss/discussions/16517) -- community reports of broken dark mode after upgrade
|
||||
- [Tailwind specificity discussion #12714](https://github.com/tailwindlabs/tailwindcss/discussions/12714) -- class collisions with component libraries
|
||||
- [BOIA: Dark Mode and WCAG Contrast](https://www.boia.org/blog/offering-a-dark-mode-doesnt-satisfy-wcag-color-contrast-requirements) -- dark mode does not auto-satisfy WCAG
|
||||
- [Complete Dark Mode Accessibility Guide (2026)](https://blog.greeden.me/en/2026/02/23/complete-accessibility-guide-for-dark-mode-and-high-contrast-color-design-contrast-validation-respecting-os-settings-icons-images-and-focus-visibility-wcag-2-1-aa/) -- WCAG 2.1 AA guidance for dark mode
|
||||
- [MUI MD3 adoption discussion #29345](https://github.com/mui/material-ui/issues/29345) -- MD3 implementation complexity
|
||||
- [React Context performance optimization](https://medium.com/zestgeek/performance-optimization-techniques-with-reacts-usecontext-5dc7e4ef6b25) -- re-render prevention patterns
|
||||
- Codebase analysis: 73 className usages, 131 test selectors across 5 files, 3 inline styles in StepIndicator, FieldRenderer aria-describedby gap confirmed (HIGH confidence -- direct code inspection)
|
||||
|
||||
---
|
||||
*Pitfalls research for: UI polish overhaul (MD3, dark mode, accent colors) on Ready2Blob v1.2*
|
||||
*Researched: 2026-03-31*
|
||||
|
||||
Reference in New Issue
Block a user