Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save prettyirrelevant/aef1231da91b40af4f51e357d41dd74c to your computer and use it in GitHub Desktop.

Select an option

Save prettyirrelevant/aef1231da91b40af4f51e357d41dd74c to your computer and use it in GitHub Desktop.
Support Engineer Task: Submissions Comparison

Support Engineer Task: Submissions Comparison

Comparison of three submissions against the Support Engineer Task requirements. Each submission was reviewed line-by-line, tracing every execution path for correctness, logic errors, security issues, and adherence to the spec.

Candidate Repository Tech Stack Issues Found
lady-thee helios-form Python, FastAPI, MongoDB (Beanie ODM) 58
TijanAyo formplus-support-engineer-task TypeScript, Express 5, MongoDB (Mongoose), mathjs 61
ruggedwizard support-assessment Python, FastAPI, MongoDB (Motor) 29

1. Core Models

Model lady-thee TijanAyo ruggedwizard
Form Beanie Document: name, description, latest_version_id, created_at Mongoose: name, currentVersionId (ObjectId ref), auto timestamps Pydantic: id: Optional[str], name, versions list, current_version
FormVersion Beanie Document: form_id (str), version_number, form_schema, created_at Mongoose: formId (ObjectId), version, formSchema (Mixed), changelog (Mixed), createdAt Pydantic (nested in Form): version_id, schema, created_at, changelog
Schema Embedded Pydantic model Mixed subdocument, TS interfaces define shape Pydantic model with fields: List[FieldSchema]
Submission Beanie Document: form_id (str), version_id (str), data, submitted_at Mongoose: formId, formVersionId, data (Mixed), computedData (Mixed), submittedAt Pydantic: id: Optional[str], form_id, version_id, data, submitted_at

Model-level bugs

Bug lady-thee TijanAyo ruggedwizard
Timestamps broken datetime.now() evaluated at class definition time, ALL documents share the same timestamp (the moment the server started) No issue (Date.now correctly called per-document) datetime.utcnow() called correctly per-document, but deprecated since Python 3.12
Type safety at persistence boundary form_id/version_id stored as str instead of PydanticObjectId, causing type mismatch bugs in queries Schema.Types.Mixed on formSchema, data, computedData, changelog provides zero runtime type safety. TS types are a complete facade. form_id stored as string instead of ObjectId, breaks MongoDB best practices and $lookup
Response model mismatches FormCreateResponse.description: str but model allows Optional[str]. created_at is datetime in one response and str in another. N/A (no response models defined) Optional[str] on Form.id and Submission.id misleads API consumers
Computed data separation Mixed into data Clean separation (data + computedData) Mixed into data
@types/mathjs conflict N/A Uses deprecated @types/mathjs v9 with mathjs v15 (ships own types). Conflict hidden by skipLibCheck: true N/A
Rating 4/10 7/10 6/10

2. Functional Requirements

2a. create_form(schema)

Criteria lady-thee TijanAyo ruggedwizard
Function exists Yes Yes Yes
Validates duplicate fields Yes Yes Yes
Validates computed refs Yes, but regex matches Python keywords (if, else, True) causing false rejections Yes, but regex matches mathjs builtins (sqrt, pi, abs, sin, round) causing false rejections. No mathjs function can ever be used in expressions. Yes, but has dead isdigit() check and same false-rejection issue
Validates visibility refs Yes, but no circular dependency detection Yes, but no circular dependency detection Yes, but operator is unvalidated str (typo silently hides field)
Validates field type is valid Yes (Pydantic Literal catches at request level) No (runtime req.body not validated, invalid types like "textarea" accepted and stored) Yes (Pydantic FieldType enum)
Validates field name format No (empty string, special chars accepted) No (empty string, special chars accepted) No
Validates expression syntax No (syntactically invalid expressions pass schema validation, fail at eval time) No (same issue) No
Validates dropdown has options Yes Yes No
Validates table has columns N/A Yes N/A
Empty schema {fields: []} allowed Unclear Yes (silently creates useless form) Unclear
Atomic DB operation No (3 separate writes, no transaction) No (3 separate writes, no transaction) No (read-modify-write, no transaction)
Rating 6/10 6/10 6/10

2b. update_form(form, schema)

Criteria lady-thee TijanAyo ruggedwizard
Function exists Yes Yes Yes
Creates new version Yes Yes Yes
Validates schema Yes Yes Yes
Records changelog/diff Yes Yes (but JSON.stringify comparison is key-order sensitive) Yes
Guards against no-op updates No No No (creates new version even for identical schema)
Version number correct No (response reports N+2 instead of N+1) Yes Yes
Race condition No transactions, but separate documents No transactions, but separate documents Read-modify-write can lose versions under concurrent access
Duplicate DB fetch Yes (fetches latest version twice, first with wrong type) No No
latest_version_id=None handled No (PydanticObjectId(None) crashes with 500) No (FormVersion.findById(null) returns null, throws "not found") N/A (versions embedded)
Rating 4/10 7/10 6/10

2c. validate_submission(submission, form, version?)

Criteria lady-thee TijanAyo ruggedwizard
Accepts optional specific version No (always uses latest, violates spec) Yes Yes
Text validation Type check, min/max length Type check, minLength/maxLength Type check, but min_length=0 truthy bug skips check
Number validation Completely broken (field.min/field.max instead of field.min_value/field.max_value, crashes with AttributeError) Works, but NaN passes all validation (typeof NaN === "number" is true, NaN < min is false) Works
Email validation Regex (accepts some malformed emails, email-validator package installed but unused) Regex Extremely weak ("@" in val accepts "@", "@@@@", "not-email @")
Dropdown validation Case-sensitive, silently passes if options is None Unsafe as string cast, confusing error if options undefined Works
Checkbox validation bool check, but Python isinstance(True, int) is True so numbers could leak through boolean check, false passes "required" check bool check
Table validation List of dicts with row count (no column/type validation) Required column checks (but column types completely ignored, no cell type validation) isinstance(val, list) only (zero content validation)
Bool accepted as number Yes (bool is subclass of int in Python, True accepted as number 1) No No
Condition evaluation Equality only 5 operators (eq/neq/gt/lt/contains), but eq uses strict === (fails across types), neq with undefined field makes field visible 4 operators, but gt/lt with type mismatch raises TypeError (crashes validation)
Multiple errors per field Single error string per field Array of errors per field (best format) Errors overwrite each other (only last error survives)
Extra/unknown fields Silently stored Silently stored Silently stored
Hidden field data Unclear Silently stored Stored unvalidated (hidden fields skip validation but data persists)
Invalid ObjectId handling Unhandled 500 Mongoose CastError leaked in 400 response N/A (string IDs)
Dry-run endpoint No Yes Yes (but response keys inconsistent: version_used vs schema_version_used)
Rating 3/10 6/10 4/10

2d. submit(form, submission)

Criteria lady-thee TijanAyo ruggedwizard
Calls validate_submission Yes Yes Yes
Computed field engine eval() with {"__builtins__": {}} (trivially bypassable, RCE) mathjs.evaluate() (safer but not fully sandboxed, user data passed directly as scope, field names can shadow mathjs functions) eval() with restricted builtins (trivially bypassable, RCE)
Computed field errors Silently sets value to None (no error, no logging) Entire submission fails with 400 (exposes schema internals in error message) Validation fails entirely
Computed field ordering No topological sort (field A depending on field B fails if A is listed first) Same issue (evaluated sequentially, data scope doesn't include prior computed values) Same issue
Race condition No Yes (form fetched twice, concurrent update between validation and save causes version mismatch) No
Duplicate DB queries No Yes (form fetched in validateSubmission then again in submit) No
Saves with timestamp Yes (but all timestamps identical, Bug 1) Yes (correct) Yes (correct)
Saves with version ref Yes Yes Yes
Rating 4/10 6/10 5/10

2e. all_submissions(form)

Criteria lady-thee TijanAyo ruggedwizard
Normalizes to latest schema Yes Yes Yes, but retroactively recalculates computed fields with new expressions on old data
Preserves raw data No No Yes (returns both, but normalization is misleading)
Handles renamed fields No (data lost) No (data lost) No (data lost)
Error handling N/A N/A Bare except: pass swallows ALL errors including SystemExit/KeyboardInterrupt
Pagination No No (loads ALL submissions into memory, OOM risk) No (hardcoded limit=1000, silently truncates)
Performance N/A O(n*m*m) field lookups (.find() inside nested loops, should use Map) N/A
Computed field stale values N/A (computed values stored inline) Stale values served from computedData (old expression), new computed fields become null Mixed: stored values kept, missing values recalculated with wrong (new) expression
Rating 5/10 5/10 3/10

3. Important Notes Compliance

Criteria lady-thee TijanAyo ruggedwizard
Forward/backward compatibility Partial (data preserved in DB, but hidden fields dropped in API, no raw access) Partial (each submission tracks formVersionId, but stale computed values, no re-evaluation) Broken (retroactive recalculation actively corrupts historical computed values)
NoSQL database (MongoDB) Yes Yes Yes
Immutable versions Yes (separate documents) Yes (never mutated) Nominally (embedded list), but $set on entire versions array means concurrent update can overwrite
Rating 5/10 7/10 4/10

4. Nice to Haves

Criteria lady-thee TijanAyo ruggedwizard
Unit tests None ~63 unit + 8 integration tests across 8 files None
Test quality N/A Several issues: try/catch without expect.assertions() (false positive risk), shared mutable state across tests (order-dependent), missing edge cases (NaN, empty schema, concurrent operations, mathjs functions in expressions) N/A
Error formatting Partial (flat dict for submissions, string list for schema) Best: field-level error arrays with human-readable messages using field labels, proper HTTP status codes Partial, but errors overwrite each other (only last error per field shown)
Documentation Good README (endpoints, examples, field types) Minimal README (no request/response examples, no schema format docs) Good README (cURL examples), but references .env.sample that doesn't exist
Docker/infra No Yes (Docker Compose with MongoDB + mongo-express UI) No
Installability Broken (requirements.txt is UTF-16 encoded, pip install fails) Works Works
Unused dependencies email-validator installed but hand-rolled regex used instead, sentry-sdk installed but never configured @types/mathjs deprecated and conflicts with mathjs v15 jsonschema in requirements but never imported
Rating 2/10 7/10 2/10

5. Security

Vulnerability lady-thee TijanAyo ruggedwizard
Remote Code Execution eval() with {"__builtins__": {}} is trivially bypassable via ().__class__.__bases__[0].__subclasses__() mathjs.evaluate() is powerful but more limited than Python's eval. Still, mathjs docs explicitly warn it's not sandboxed. Same as lady-thee, plus whitelisted builtins (abs, min, max, round) expand attack surface
Internal info leakage Unhandled exceptions expose stack traces All errors return 400 with raw err.message, leaks Mongoose CastErrors, MongoDB ObjectIds, internal schema details Custom exception hierarchy (better)
Request validation Pydantic validates request bodies (good) Zero runtime request validation. Malformed body crashes with raw TypeError. Pydantic validates request bodies (good)
Extra field injection Unvalidated extra fields stored in DB Unvalidated extra fields stored in DB Unvalidated extra fields stored in DB
No auth/rate limiting/CORS Yes Yes Yes
Rating 3/10 4/10 3/10

6. Code Quality and API Design

Criteria lady-thee TijanAyo ruggedwizard
Architecture Layered (routes, services, validators, models) Layered (models, services, utils, routes) God class (FormEngine handles CRUD, validation, submission, normalization, computed evaluation)
Cannot retrieve form schema No endpoint returns the form schema/field definitions. Consumers cannot see what fields a form has. Schema returned in create/update responses Schema returned in responses
HTTP status codes Appropriate (400, 404, 422) All errors return 400 regardless of type (not-found, validation, server error) Appropriate (400, 404, 422)
Runtime crashes on basic operations GET /api/forms crashes every time (.model_dump() on list). Number validation crashes on every number field with min/max. Malformed request body crashes (no runtime validation) gt/lt condition with type mismatch crashes
DB connection handling Missing env vars silently connect to localhost with DB named "None" Proper connection wrapper Motor client created at module import (before event loop)
DB indexes None None None
N+1 queries Yes (get_forms queries each version separately) Yes (form fetched twice in submit) No
TypeScript type safety N/A strict: true but defeated by Mixed schemas, any casts in catches, as string/as number unsafe casts, skipLibCheck: true N/A
Rating 3/10 5/10 3/10

7. Summary Scores

Category Weight lady-thee TijanAyo ruggedwizard
Core Models 10% 4/10 7/10 6/10
create_form 12% 6/10 6/10 6/10
update_form 10% 4/10 7/10 6/10
validate_submission 15% 3/10 6/10 4/10
submit 10% 4/10 6/10 5/10
all_submissions 10% 5/10 5/10 3/10
Forward/Backward Compatibility 8% 5/10 7/10 4/10
Nice to Haves 10% 2/10 7/10 2/10
Security 7% 3/10 4/10 3/10
Code Quality & API Design 8% 3/10 5/10 3/10
Weighted Total 100% 3.87/10 6.02/10 4.18/10

8. Final Ranking

Rank Candidate Score Verdict
1 TijanAyo 6.02/10 Best of the three, but far from production-ready. Key strengths: only candidate with tests (~63 unit + 8 integration), uses mathjs instead of eval(), cleanest model design (separates computed data), richest conditional logic, Docker Compose, TypeScript strict mode. Key weaknesses: TS type safety is a facade over Mixed schemas, zero runtime request validation (malformed body crashes), all errors return 400, expression regex rejects all mathjs functions, computed fields can't reference other computed fields, race condition between validation and submission, stale computed values in normalization.
2 ruggedwizard 4.18/10 Addresses all five requirements, but the implementation has deep issues. The FormEngine god class does everything. all_submissions has a bare except: pass and retroactively recalculates computed values (corrupts historical data). Validation errors overwrite each other (only last error per field). min_length=0 truthy bug. Condition operators are unvalidated strings. gt/lt comparisons crash on type mismatch. eval() for computed fields (RCE). No tests.
3 lady-thee 3.87/10 All requirements addressed structurally, but multiple critical runtime failures make core features non-functional. GET /api/forms crashes on every call (.model_dump() on list). Number min/max validation crashes (wrong attribute names). All timestamps are identical (class-level datetime.now()). requirements.txt is corrupted (project can't be installed). No endpoint to retrieve form schemas. Version off-by-one in update response. eval() for computed fields (RCE). No tests.

9. Issue Catalog by Candidate

lady-thee (helios-form): 58 issues

Critical runtime crashes (7)
  1. datetime.now() evaluated at class definition time; all documents share server-start timestamp
  2. _validate_number accesses field.min/field.max which don't exist (model defines min_value/max_value); crashes with AttributeError
  3. GET /api/forms calls .model_dump() on a List[FormResponse]; crashes with AttributeError every time
  4. eval() with {"__builtins__": {}} is trivially bypassable for remote code execution
  5. get_forms_service compares PydanticObjectId to str in version lookup; never matches, version always reports 0
  6. update_form_service response reports version N+2 instead of N+1 (off-by-one)
  7. PydanticObjectId(None) crashes when latest_version_id is None (multiple locations)
Logic/validation bugs (18)
  1. _extract_field_references regex matches Python keywords (if, else, True), falsely rejecting valid expressions
  2. _validate_email uses hand-rolled regex that accepts malformed emails; email-validator package installed but unused
  3. bool is subclass of int in Python, so True/False pass number validation as 1/0
  4. _validate_dropdown is case-sensitive and silently passes if options is None
  5. _validate_table has no column/type validation (any list of dicts passes)
  6. date/file/signature field types accepted in schema but zero validation at submission time
  7. evaluate_computed_fields silently sets value to None on any error (no logging)
  8. evaluate_computed_fields depends on field order (no topological sort for computed dependencies)
  9. validate_submission doesn't check for extra/unknown fields in submission data
  10. validate_submission doesn't support version-specific validation (always uses latest, violates spec)
  11. normalize_submission drops fields not in latest schema (data loss)
  12. _check_computed doesn't validate expression syntax
  13. _check_min_max accepts negative min_length/max_length values
  14. _check_visible_when no circular dependency detection
  15. _check_visible_when doesn't validate equals value against field type
  16. Required check for table passes empty list (rejects at table validation with wrong error message)
  17. compute_changelog does O(n*m) comparison (should use dict lookup)
  18. description is Optional[str] in model but str in response schemas
API/design issues (18)
  1. Duplicate DB fetch with type mismatch in update_form_service (str vs PydanticObjectId)
  2. created_at is datetime in one response schema and str in another
  3. No GET /api/forms/{form_id} endpoint (cannot retrieve single form or its schema)
  4. No endpoint returns form schema/field definitions
  5. No error handling for invalid ObjectId format (unhandled 500s)
  6. All routes use manual JSONResponse, bypassing FastAPI's response model validation
  7. POST /forms/submit returns 201 with no idempotency protection
  8. No global exception handler
  9. No CORS middleware
  10. N+1 queries in get_forms_service
  11. No DB indexes
  12. get_forms route function named singular (get_form) but returns all forms
  13. Missing env vars: DB named "None", connects to localhost silently
  14. load_dotenv() at import time locks in values
  15. init_db creates new client on every call
  16. Unused imports (init_db in services, Optional in validators)
  17. print for logging instead of logging module
  18. requirements.txt is UTF-16 encoded (pip install fails)
Data integrity issues (6)
  1. No transactions on multi-step DB operations (3 separate writes for form creation)
  2. Extra/unknown fields in submissions silently stored
  3. latest_version_id=None not handled (crashes in multiple services)
  4. update_form_service doesn't check form_id path param matches form.id
  5. sentry-sdk installed but never configured 49-58. Various response model field mismatches and Beanie configuration concerns

TijanAyo (formplus-support-engineer-task): 61 issues

TypeScript type safety lies (7)
  1. Schema.Types.Mixed on formSchema completely defeats TypeScript typing; TS types are a facade
  2. Same for changelog field
  3. Same for Submission data and computedData
  4. tsconfig.json excludes tests from compilation (tsc never type-checks tests)
  5. skipLibCheck: true hides type conflicts in dependencies
  6. Deprecated @types/mathjs v9 conflicts with mathjs v15 (hidden by skipLibCheck)
  7. Pervasive err: any casts in all route handlers
Security (5)
  1. mathjs.evaluate() with user-supplied data as scope is not fully sandboxed
  2. User-supplied data can shadow mathjs functions (field named sqrt replaces the function)
  3. Error messages leak MongoDB ObjectIds and Mongoose internals
  4. No request body size limit configured
  5. No auth, rate limiting, or CORS
FormService logic bugs (8)
  1. validateSchema crashes on null/undefined schema (no runtime validation of req.body.schema)
  2. createForm doesn't validate name (undefined, null, numbers accepted)
  3. Expression validation regex rejects ALL mathjs functions (sqrt, abs, round, pow, log, sin, etc.)
  4. Empty schema.fields array silently creates a useless form
  5. No validation that field type is a valid FieldType at runtime
  6. No validation of field name format (empty string, special chars accepted)
  7. Computed field can depend on another computed field but evaluateAll doesn't include prior computed values in scope
  8. Non-atomic form creation (3 separate writes, no transaction)
ValidationService logic bugs (9)
  1. Invalid ObjectId format causes Mongoose CastError leaked to client
  2. form.currentVersionId null causes unhelpful "not found" error
  3. Dropdown validation uses unsafe as string cast, confusing error if options undefined
  4. Required checkbox: false passes required check (debatable correctness)
  5. NaN passes all number validation (typeof NaN === "number" is true)
  6. Table column types completely ignored (column type field never validated)
  7. Table rows accept extra columns beyond schema definition
  8. Empty string skips all validation for non-required fields (problematic for non-required numbers)
  9. Extra/unknown fields in submission silently accepted and stored
SubmissionService logic bugs (7)
  1. Form fetched twice in submit (once in validateSubmission, once in submit)
  2. Race condition: concurrent updateForm between validation and save causes version mismatch
  3. evaluateAll failure crashes entire submission (exposes schema internals in error)
  4. allSubmissions serves stale computed values; new computed fields become null
  5. No pagination on allSubmissions (loads ALL submissions into memory)
  6. O(nmm) field lookups in normalization (.find() inside nested loops)
  7. Non-null assertion ! on potentially undefined value
Expression and visibility evaluator issues (6)
  1. mathjs.evaluate can return non-number types (matrices, complex numbers, booleans)
  2. mathjs can mutate the scope object (e.g., expression "x = 42" modifies submission data in memory)
  3. gt/lt silently return false for non-number values (no error)
  4. eq uses strict equality (fails for string/number comparisons, fails for object/array comparisons)
  5. neq with undefined field makes field visible (asymmetric with eq behavior)
  6. Default case returns true (unknown operators silently make fields visible)
Schema diff issues (2)
  1. Duplicate field names cause silent data loss in Map
  2. JSON.stringify comparison is key-order sensitive (false "modified" detections)
Route handler issues (2)
  1. PUT/POST/GET return 400 for "not found" instead of 404
  2. All internal server errors return 400 instead of 500 (leaks internals)
Test quality issues (8)
  1. try/catch without expect.assertions() allows silent false positives
  2. No test for invalid ObjectId format
  3. No test for concurrent operations / race conditions
  4. No tests for expression edge cases (mathjs functions, assignment operators, undefined vars)
  5. No test for NaN number values
  6. No test for empty schema
  7. Integration test doesn't verify stale computed value behavior
  8. SubmissionService tests are order-dependent (shared mutable state)
Model and infrastructure issues (7)
  1. No index on Form.name (no uniqueness constraint)
  2. No compound index on FormVersion(formId, version) (race condition can create duplicate versions)
  3. No index on Submission.formId (full collection scan)
  4. Inconsistent timestamp handling (timestamps: true vs manual submittedAt)
  5. No graceful shutdown handling (SIGTERM/SIGINT)
  6. No global error handling middleware
  7. No 404 handler for unmatched routes

ruggedwizard (support-assessment): 29 issues

Critical (1)
  1. eval() with restricted builtins is trivially bypassable for remote code execution
Runtime crashes (2)
  1. greater_than/less_than condition operators raise TypeError on type mismatch
  2. README references .env.sample that doesn't exist
Silent wrong results (5)
  1. errors[f.name] = ... overwrites previous errors (only last error per field survives)
  2. min_length=0 treated as "no constraint" due to truthy check
  3. Bare except: pass swallows ALL errors including SystemExit/KeyboardInterrupt
  4. all_submissions retroactively recalculates computed fields with new expressions on old data
  5. Unvalidated operator string; typo silently returns False, permanently hiding field
Data integrity (4)
  1. Read-modify-write race in update_form can lose schema versions
  2. Hidden fields skip validation but data stored unvalidated
  3. Dead isdigit() check in expression validation
  4. No transactions on multi-step DB operations
Design/code quality (12)
  1. FormEngine god class
  2. Email validation is "@" in val
  3. Table validation: isinstance(val, list) only
  4. _doc_to_form mutates input dict
  5. form_id stored as string instead of ObjectId
  6. Optional[str] on id fields misleads consumers
  7. datetime.utcnow() deprecated
  8. Triple-quoted strings as section dividers (not docstrings)
  9. Motor client created before event loop
  10. No DB indexes
  11. Hardcoded limit=1000, silently truncates
  12. No-op updates create new versions
Missing (5)
  1. Zero tests
  2. No CORS
  3. No .env.sample
  4. No pagination
  5. No rename tracking in changelog

10. Conclusion

All three submissions have fundamental issues that would prevent production deployment. The most significant finding from the deep review is that issue counts are much higher than surface-level review suggests, and the nature of the bugs reveals how thoroughly (or not) each candidate tested their own code.

lady-thee has bugs that would be caught by running the code even once (GET /api/forms crashes, number validation crashes, corrupted requirements.txt prevents installation). This suggests the code was never executed end-to-end.

TijanAyo has the most issues by count (61), but the majority are edge cases, missing validations, and TypeScript-specific concerns rather than core logic failures. The existence of ~71 tests shows the code was actually run and tested, even though the test suite has its own quality issues. The TypeScript type safety is largely theatrical (Mixed schemas defeat it at the persistence boundary), and the expression regex bug means no mathjs function can be used in computed expressions, which undermines the choice of mathjs.

ruggedwizard's code reads like a first draft: the god class, bare except: pass, error overwriting, truthy bugs, and complete absence of tests all point to code written in one pass without review. The retroactive computed field recalculation in all_submissions is a design-level mistake that actively corrupts data, which is worse than simply losing data.

TijanAyo remains the strongest candidate. Despite the high issue count, the submission demonstrates meaningfully better engineering practices than the other two, and its issues are categorically less severe (edge cases vs. core functionality failures).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment