-
-
Notifications
You must be signed in to change notification settings - Fork 89
Develop #537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop #537
Changes from all commits
c8be76d
376db6b
84bf30a
f301a10
dfd5874
f5423fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| namespace Resgrid.Config | ||
| { | ||
| /// <summary> | ||
| /// Passkeys, Responder approval and provider step-up (passkey plan sections 10.2-10.3; Phase 0 workbook sections 5 | ||
| /// and 12). Every rollout gate starts OFF. A gate that is ON still does nothing unless the relying-party registry | ||
| /// validates at startup, so a half-configured deployment fails closed. Turning a gate off stops new use only; it never | ||
| /// removes durable revocations or makes an old grant valid. | ||
| /// </summary> | ||
| public static class PasskeyConfig | ||
| { | ||
| // ── Rollout gates (all OFF) ─────────────────────────────────────────────────── | ||
|
|
||
| /// <summary>Allow users to register passkeys.</summary> | ||
| public static bool RegistrationEnabled = false; | ||
|
|
||
| /// <summary>Accept passkeys as login MFA.</summary> | ||
| public static bool LoginAcceptanceEnabled = false; | ||
|
|
||
| /// <summary>Accept passkey evidence for Protected Data Grants.</summary> | ||
| public static bool AdpAcceptanceEnabled = false; | ||
|
|
||
| /// <summary>Issue version 2 Protected Data Grants. Every reader must support v2 before this is turned on.</summary> | ||
| public static bool EmitGrantV2 = false; | ||
|
|
||
| /// <summary>Allow shared-device (vehicle tablet / dispatch workstation) sessions.</summary> | ||
| public static bool SharedDeviceModeEnabled = false; | ||
|
|
||
| /// <summary>Allow "Approve with Responder" cross-app MFA.</summary> | ||
| public static bool ResponderApprovalEnabled = false; | ||
|
|
||
| /// <summary>Allow provider step-up (federated MFA) for departments that opt in.</summary> | ||
| public static bool ProviderStepUpEnabled = false; | ||
|
|
||
| // ── Relying parties (one per client; workbook section 5) ────────────────────── | ||
|
|
||
| /// <summary> | ||
| /// One relying party per client, separated by ";". Each entry is <c>client=rpId|origin,origin</c>, where client is | ||
| /// web, responder, unit, dispatch or command (ic), the RP ID is that client's own host, and each origin is | ||
| /// <c>https://host[:port]</c> under the RP ID or <c>android:apk-key-hash:<base64url></c>. Example: | ||
| /// <c>web=app.resgrid.com|https://app.resgrid.com;unit=unit.resgrid.com|https://unit.resgrid.com,android:apk-key-hash:abc</c>. | ||
| /// Empty means passkeys are unavailable on this deployment. | ||
| /// </summary> | ||
| public static string RelyingParties = ""; | ||
|
|
||
| /// <summary>Name the platform shows in the passkey prompt.</summary> | ||
| public static string RelyingPartyName = "Resgrid"; | ||
|
|
||
| // ── Ceremony limits ─────────────────────────────────────────────────────────── | ||
|
|
||
| public static int RegistrationChallengeLifetimeSeconds = 300; | ||
|
|
||
| public static int AssertionChallengeLifetimeSeconds = 120; | ||
|
|
||
| /// <summary>Failed verifications allowed against one challenge before it is spent.</summary> | ||
| public static int ChallengeMaxAttempts = 5; | ||
|
|
||
| /// <summary>Pending challenges one user may hold at once; more is refused rather than queued.</summary> | ||
| public static int MaxOutstandingChallengesPerUser = 10; | ||
|
|
||
| /// <summary>Active passkeys per user per client (at most 5 clients).</summary> | ||
| public static int MaxActiveCredentialsPerClient = 10; | ||
|
|
||
| public static int MaxDisplayNameLength = 100; | ||
|
|
||
| // ── Responder approval (plan section 7.9 abuse controls) ────────────────────── | ||
|
|
||
| /// <summary>An approval request lives this long and is never extended.</summary> | ||
| public static int ApprovalRequestLifetimeSeconds = 120; | ||
|
|
||
| /// <summary>Wrong numbers allowed before the request is denied.</summary> | ||
| public static int ApprovalMaxNumberAttempts = 3; | ||
|
|
||
| /// <summary>Approval requests one user may create per <see cref="ApprovalRateWindowMinutes"/>.</summary> | ||
| public static int ApprovalMaxRequestsPerWindow = 5; | ||
|
|
||
| public static int ApprovalRateWindowMinutes = 15; | ||
|
|
||
| /// <summary>After two denials or expiries in a row (or one "not me"), new requests are refused this long.</summary> | ||
| public static int ApprovalSuspensionMinutes = 15; | ||
|
|
||
| /// <summary>How long after its expiry an approved request can still be used by the requester's final poll.</summary> | ||
| public static int ApprovalConsumeGraceSeconds = 30; | ||
|
|
||
| // ── Shared vehicle and workstation sessions (plan sections 10.5 and 12.5) ───── | ||
|
|
||
| /// <summary>The longest idle lock a department may choose (at most 15 minutes).</summary> | ||
| public static int SharedMaxIdleLockMinutes = 15; | ||
|
|
||
| /// <summary>The longest shift a department may choose (at most 24 hours).</summary> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SharedMaxShiftHours permits shared sessions to last 24 hours, exceeding the required maximum session timeout. Limit the absolute shared-session duration to 12 hours or less. Kody rule violation: Harden session management with idle and absolute timeouts public const int SharedMaxShiftHours = 12;Prompt for LLMTalk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction. |
||
| public static int SharedMaxShiftHours = 24; | ||
|
|
||
| /// <summary>Operator activity is written at most this often per session, so a busy screen is not a write per request.</summary> | ||
| public static int SharedActivityWriteIntervalSeconds = 30; | ||
|
|
||
| /// <summary>Unlock attempts one shared session may make per 5 minutes, on top of the account lockout.</summary> | ||
| public static int SharedUnlockMaxAttempts = 5; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BrokerLegacySharedKeyEnabledenables a full-authority legacy shared credential by default, violating deny-by-default and least-privilege principles during migration. Disable it by default and require an explicit, scoped authorization path.Kody rule violation: Implement RBAC with least privilege and deny-by-default
Prompt for LLM
Talk to Kody by mentioning @kody
Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.