Skip to content

Conversation

evanpelle
Copy link
Collaborator

@evanpelle evanpelle commented Aug 14, 2025

Description:

Some flags are offensive, so don't allow them to be selected by users.

I think it's fine for nations continue to use the flags.

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

Please put your Discord username so you can be contacted if a bug or regression is found:

evan

Copy link
Contributor

coderabbitai bot commented Aug 14, 2025

Walkthrough

Adds a restricted flag to three country entries, excludes restricted countries from FlagInputModal search results, and removes restricted codes from FlagSchema validation. No exported/public API signatures changed.

Changes

Cohort / File(s) Summary of changes
Flag input filtering
src/client/FlagInputModal.ts
Filter now excludes countries with restricted: true before applying name/code search matching; a new private helper includedInSearch encapsulates the name/code match. Rendering and events unchanged.
Country data annotations
src/client/data/countries.json
Added "restricted": true to three country objects: Confederate States, Fascist Spain, German Empire. No other fields changed.
Schema validation
src/core/Schemas.ts
countryCodes now built from countries.filter(c => !c.restricted).map(c => c.code), so FlagSchema only accepts non-restricted country codes.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant FlagInputModal
  participant CountriesData
  participant Schemas

  User->>FlagInputModal: Type search query
  FlagInputModal->>CountriesData: Request country list
  CountriesData-->>FlagInputModal: Return countries (some have restricted=true)
  FlagInputModal->>FlagInputModal: Exclude restricted, then includedInSearch check
  User->>FlagInputModal: Select country
  FlagInputModal->>Schemas: Validate selected code
  Schemas->>Schemas: Check code against non-restricted countryCodes
  Schemas-->>FlagInputModal: Validation result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

Suggested labels

Feature - Flags, Exploits and Security

Suggested reviewers

  • scottanderson

Poem

Three flags marked quiet, hidden from view,
Searches trim the list to the safer few.
Schemas check codes, only allowed remain,
Small, tidy change — the rules now maintain. 🎏

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 32fe3a5 and 9a2019c.

📒 Files selected for processing (3)
  • src/client/FlagInputModal.ts (2 hunks)
  • src/client/data/countries.json (3 hunks)
  • src/core/Schemas.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/core/Schemas.ts
  • src/client/data/countries.json
  • src/client/FlagInputModal.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Deploy to openfront.dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@evanpelle evanpelle changed the base branch from main to v25 August 14, 2025 03:20
@evanpelle evanpelle force-pushed the evan-restrict-problematic-flags branch from 796abe5 to da0002a Compare August 14, 2025 03:21
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (3)
src/core/Schemas.ts (3)

193-205: Critical: validation now blocks server-sent NPC flags (violates PR goal)

By filtering out restricted codes at the source and using a single FlagSchema, any payload containing a restricted flag (e.g., NPC nation in GameStartInfo) will fail validation. The PR goal says: “prevent users from selecting these flags while allowing nations to continue using them.”

Split schemas:

  • ClientFlagSchema: only non-restricted codes (for client-submitted data: SpawnIntent, ClientJoin, etc.).
  • ServerFlagSchema: full set (for server-sent Player/records).

Apply this diff here to define both variants and keep FlagSchema as the restricted one for backward compatibility in client inputs:

-export const UsernameSchema = SafeString;
-const countryCodes = countries.filter((c) => !c.restricted).map((c) => c.code);
-export const FlagSchema = z
-  .string()
-  .max(128)
-  .optional()
-  .refine(
-    (val) => {
-      if (val === undefined || val === "") return true;
-      if (val.startsWith("!")) return true;
-      return countryCodes.includes(val);
-    },
-    { message: "Invalid flag: must be a valid country code or start with !" },
-  );
+export const UsernameSchema = SafeString;
+const allCountryCodes = countries.map((c) => c.code);
+const allowedClientCountryCodes = countries
+  .filter((c) => !c.restricted)
+  .map((c) => c.code);
+
+export const ClientFlagSchema = z
+  .string()
+  .max(128)
+  .optional()
+  .refine(
+    (val) => {
+      if (val === undefined || val === "") return true;
+      if (val.startsWith("!")) return true;
+      return allowedClientCountryCodes.includes(val);
+    },
+    { message: "Invalid flag: must be a valid country code or start with !" },
+  );
+
+export const ServerFlagSchema = z
+  .string()
+  .max(128)
+  .optional()
+  .refine(
+    (val) => {
+      if (val === undefined || val === "") return true;
+      if (val.startsWith("!")) return true;
+      return allCountryCodes.includes(val);
+    },
+    { message: "Invalid flag: must be a valid country code or start with !" },
+  );
+
+// Keep existing name for client-submitted usage sites
+export const FlagSchema = ClientFlagSchema;

Then update usage sites (see next comment) so server-to-client schemas accept ServerFlagSchema.


396-401: Use ServerFlagSchema for server-sent Player data

GameStartInfoSchema.players and GameEndInfo/records include NPC nations. They should be allowed to carry restricted flags. Switch PlayerSchema.flag to ServerFlagSchema.

 export const PlayerSchema = z.object({
   clientID: ID,
   username: UsernameSchema,
-  flag: FlagSchema,
+  flag: ServerFlagSchema,
   pattern: PatternSchema,
 });

Also adjust any other server-sent schemas that embed PlayerSchema (GameStartInfoSchema, GameEndInfoSchema) indirectly via this change.


255-262: Keep restricted validation for client-submitted SpawnIntent.flag

rg shows the schema still uses FlagSchema (not a client-specific variant) in three places. If you have a client/server FlagSchema split, update these to ClientFlagSchema — otherwise confirm FlagSchema is intentionally an alias of the client variant.

Locations:

  • src/core/Schemas.ts — flag: FlagSchema at line 258 (SpawnIntentSchema, ~255–262)
  • src/core/Schemas.ts — flag: FlagSchema at line 399
  • src/core/Schemas.ts — flag: FlagSchema at line 505

Suggested minimal change:

  • flag: FlagSchema,
  • flag: ClientFlagSchema,

If FlagSchema already aliases ClientFlagSchema, no change needed — otherwise please make the replacement above.

🧹 Nitpick comments (2)
src/client/FlagInputModal.ts (2)

20-25: Localize visible strings (title and placeholder)

These strings should go through your translateText (or equivalent) to match the PR note and the rest of the app i18n.

Apply this small diff (adjust the import according to your i18n setup):

-      <o-modal title="Flag Selector Modal" alwaysMaximized>
+      <o-modal title=${translateText("Flag Selector Modal")} alwaysMaximized>
@@
-          placeholder="Search..."
+          placeholder=${translateText("Search...")}

If translateText needs importing, add it at the top:

+import { translateText } from "./i18n"; // adjust path as needed

21-27: Prefer the input event over keyup/change for search UX

Using @input alone provides immediate updates and handles all edit cases (typing, paste, clear). It also reduces duplicate handler calls.

-          @change=${this.handleSearch}
-          @keyup=${this.handleSearch}
+          @input=${this.handleSearch}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7036a96 and da0002a.

📒 Files selected for processing (3)
  • src/client/FlagInputModal.ts (1 hunks)
  • src/client/data/countries.json (3 hunks)
  • src/core/Schemas.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: VariableVince
PR: openfrontio/OpenFrontIO#1655
File: resources/maps/giantworldmap/manifest.json:165-174
Timestamp: 2025-07-31T12:03:08.052Z
Learning: In OpenFrontIO draft PRs, flag names in map manifest files may be placeholders that will be updated to match the actual SVG flag file names when the assets are received. The final naming depends on the actual flag SVG files provided, not code naming conventions.
📚 Learning: 2025-05-21T04:10:33.435Z
Learnt from: scottanderson
PR: openfrontio/OpenFrontIO#784
File: src/core/game/StatsImpl.ts:34-38
Timestamp: 2025-05-21T04:10:33.435Z
Learning: In the codebase, PlayerStats is defined as `z.infer<typeof PlayerStatsSchema>` where PlayerStatsSchema has `.optional()` applied at the object level, making PlayerStats a union type that already includes undefined (PlayerStats | undefined).

Applied to files:

  • src/core/Schemas.ts
📚 Learning: 2025-05-21T04:10:33.435Z
Learnt from: scottanderson
PR: openfrontio/OpenFrontIO#784
File: src/core/game/StatsImpl.ts:34-38
Timestamp: 2025-05-21T04:10:33.435Z
Learning: In the codebase, PlayerStats is defined as a type inferred from a Zod schema that is marked as optional, which means PlayerStats already includes undefined as a possible type (PlayerStats | undefined).

Applied to files:

  • src/core/Schemas.ts
🔇 Additional comments (2)
src/client/data/countries.json (1)

485-489: LGTM: restricted flags are correctly marked

The new "restricted": true markers for Confederate States, Fascist Spain, and German Empire look correct and align with the UI filter.

Caution: with the current FlagSchema change (see Schemas.ts), these codes will be rejected by validation everywhere. If NPC nations still use these codes, server-sent payloads that include them will fail schema validation. See my Schemas.ts comment for a safe split between client-submitted vs. server-sent flags.

Would you like a quick check that no other flagged codes should be restricted now? I can add a script to list possibly sensitive codes and compare to the restricted list.

Also applies to: 704-708, 808-812

src/client/FlagInputModal.ts (1)

33-35: Good: restricted flags are excluded from the picker

The predicate correctly hides any country with restricted === true, even when the search matches.

No functional issues spotted here.

coderabbitai[bot]
coderabbitai bot previously approved these changes Aug 14, 2025
@evanpelle evanpelle added this to the v25 milestone Aug 14, 2025
@evanpelle evanpelle marked this pull request as ready for review August 14, 2025 04:35
@evanpelle evanpelle requested a review from a team as a code owner August 14, 2025 04:35
scottanderson
scottanderson previously approved these changes Aug 14, 2025
@github-project-automation github-project-automation bot moved this from Triage to Final Review in OpenFront Release Management Aug 14, 2025
Copy link
Contributor

@scottanderson scottanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/client/FlagInputModal.ts (3)

31-36: Make the predicate easier to read and compute the query once.

Minor readability/perf polish: precompute the normalized search once and avoid repeated toLowerCase calls inside filter.

You can refactor render() like:

const q = this.search.trim().toLowerCase();
const filtered = Countries.filter(({ restricted, name, code }) =>
  !restricted && (q === "" || name.toLowerCase().includes(q) || code.toLowerCase().includes(q)),
);

// ...
${filtered.map((country) => html`...`)}

21-27: Prefer @input over @change/@keyup for live search.

@input fires on every value change and removes the need to wire both keyup and change, simplifying logic and improving UX.

-          @change=${this.handleSearch}
-          @keyup=${this.handleSearch}
+          @input=${this.handleSearch}

48-58: Improve image accessibility, performance, and robustness.

  • Add alt text for screen readers.
  • Lazy-load and async-decode for perf.
  • URL-encode code in the src to handle spaces and special chars safely.
-                <img
-                  class="country-flag w-full h-auto"
-                  src="/flags/${country.code}.svg"
+                <img
+                  class="country-flag w-full h-auto"
+                  src="/flags/${encodeURIComponent(country.code)}.svg"
+                  alt="${country.name} flag"
+                  loading="lazy"
+                  decoding="async"
                   @error=${(e: Event) => {
                     const img = e.currentTarget as HTMLImageElement;
                     const fallback = "/flags/xx.svg";
                     if (img.src && !img.src.endsWith(fallback)) {
                       img.src = fallback;
                     }
                   }}
                 />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between da0002a and 32fe3a5.

📒 Files selected for processing (1)
  • src/client/FlagInputModal.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: VariableVince
PR: openfrontio/OpenFrontIO#1655
File: resources/maps/giantworldmap/manifest.json:165-174
Timestamp: 2025-07-31T12:03:08.052Z
Learning: In OpenFrontIO draft PRs, flag names in map manifest files may be placeholders that will be updated to match the actual SVG flag file names when the assets are received. The final naming depends on the actual flag SVG files provided, not code naming conventions.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: 🏗️ Build
  • GitHub Check: 🔍 ESLint
  • GitHub Check: 🎨 Prettier
  • GitHub Check: 🔬 Test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Deploy to openfront.dev

@github-project-automation github-project-automation bot moved this from Final Review to Development in OpenFront Release Management Aug 14, 2025
@evanpelle evanpelle force-pushed the evan-restrict-problematic-flags branch from 32fe3a5 to 9a2019c Compare August 14, 2025 18:18
@evanpelle evanpelle changed the title restrict problematic flags restrict problematic flags fixes #1690 Aug 14, 2025
@evanpelle evanpelle merged commit 294b6e0 into v25 Aug 14, 2025
13 of 18 checks passed
@evanpelle evanpelle deleted the evan-restrict-problematic-flags branch August 14, 2025 18:21
@github-project-automation github-project-automation bot moved this from Development to Complete in OpenFront Release Management Aug 14, 2025
evanpelle added a commit that referenced this pull request Aug 15, 2025
## Description:

Some flags are offensive, so don't allow them to be selected by users.

I think it's fine for nations continue to use the flags.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
scottanderson pushed a commit that referenced this pull request Aug 18, 2025
Some flags are offensive, so don't allow them to be selected by users.

I think it's fine for nations continue to use the flags.

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

regression is found:

evan
TheGiraffe3 pushed a commit that referenced this pull request Sep 4, 2025
Some flags are offensive, so don't allow them to be selected by users.

I think it's fine for nations continue to use the flags.

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

regression is found:

evan
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Complete
Development

Successfully merging this pull request may close these issues.

2 participants