Skip to content

[orchestrator] Backport orchestrator fixes and enhancements to 1.9#2667

Merged
karthikjeeyar merged 1 commit intoworkspace/orchestratorfrom
orchestrator-1.9-backport
Apr 1, 2026
Merged

[orchestrator] Backport orchestrator fixes and enhancements to 1.9#2667
karthikjeeyar merged 1 commit intoworkspace/orchestratorfrom
orchestrator-1.9-backport

Conversation

@lokanandaprabhu
Copy link
Copy Markdown
Member

Hey, I just made a Pull Request!

Cherrypick of below PR's

#2654
#2602
#2653
#2570

Summary

  • Backport Execute Workflow query param prefill
  • Backport async validation scoping to active step
  • Backport ui:hidden preservation for object properties
  • Backport schema-defaults initialization for form data

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

…2666)

* feat(orchestrator): pre-populate Execute Workflow form from URL query params (#2570)

* prepopulate workflow execution page form from URL query params

Signed-off-by: Karthik <karthik.jk11@gmail.com>

* support enum coercison for case-insenstive match and skip invalid values

* add support for fields that are defined via '$ref'

* add full support for json schema fields

---------

Signed-off-by: Karthik <karthik.jk11@gmail.com>

* fix(orchestrator-form-react): scope async validation to active step (#2602)

* fix(orchestrator-form-react): scope async validation to active step

Limit validate:url requests to the active step during multi-step navigation.

Made-with: Cursor

* fix(orchestrator-form-react): keep full formData for async validation

Pass full formData to template evaluation while scoping uiSchema traversal.

Made-with: Cursor

* fix(orchestrator-form-react): preserve ui:hidden on objects with properties (#2653)

* fix(orchestrator): honor json schema defaults in initial formData (#2654)

* fix(orchestrator): honor json schema defaults

Ensure extractStaticDefaults falls back to JSON Schema defaults when ui:props fetch:response:default is absent so initial formData includes schema defaults.

Made-with: Cursor

* chore(changeset): document schema default fix

Add changeset for orchestrator form defaults update.

Made-with: Cursor

* fix(orchestrator): handle root defaults

Avoid setting an empty key for root schema defaults and add tests to cover root default handling.

Made-with: Cursor

* fix(orchestrator): document and test defaults

Clarify extractStaticDefaults precedence in docs and add test coverage for default handling.

Made-with: Cursor

* chore(orchestrator): update yarn.lock after backport

Made-with: Cursor

---------

Signed-off-by: Karthik <karthik.jk11@gmail.com>
Co-authored-by: Karthik Jeeyar <karthik@redhat.com>
@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Backport orchestrator fixes and enhancements to 1.9

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Pre-populate Execute Workflow form from URL query parameters with full schema support
• Scope async validation to active step in multi-step forms to reduce unnecessary requests
• Preserve ui:hidden and other UI directives on object schemas with properties
• Honor JSON Schema default values in initial form data alongside fetch defaults
• Add comprehensive test coverage for query param coercion and schema resolution
Diagram
flowchart LR
  A["URL Query Params"] -->|mergeQueryParamsIntoFormData| B["Form Data"]
  C["JSON Schema"] -->|extractStaticDefaults| B
  D["Schema Defaults"] -->|fallback| C
  E["UI Schema"] -->|generateUiSchema| F["UI Directives"]
  G["Multi-step Form"] -->|scope validation| H["Active Step Only"]
  B --> I["Execute Workflow Page"]
  F --> I
  H --> I
Loading

Grey Divider

File Changes

1. workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts ✨ Enhancement +303/-0

Query parameter to form data conversion with schema validation

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts


2. workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.test.ts 🧪 Tests +650/-0

Comprehensive tests for query param prepopulation and type coercion

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.test.ts


3. workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/extractStaticDefaults.ts 🐞 Bug fix +26/-7

Support JSON Schema defaults with fetch default precedence

workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/extractStaticDefaults.ts


View more (11)
4. workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/extractStaticDefaults.test.ts 🧪 Tests +119/-0

Test coverage for schema defaults and root default handling

workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/extractStaticDefaults.test.ts


5. workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/generateUiSchema.ts 🐞 Bug fix +1/-0

Preserve UI directives on object schemas with properties

workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/generateUiSchema.ts


6. workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/generateUiSchema.test.ts 🧪 Tests +23/-0

Test UI directive preservation on object nodes

workspaces/orchestrator/plugins/orchestrator-form-react/src/utils/generateUiSchema.test.ts


7. workspaces/orchestrator/plugins/orchestrator-form-react/src/components/OrchestratorFormWrapper.tsx 🐞 Bug fix +12/-1

Scope async validation to active step in multi-step forms

workspaces/orchestrator/plugins/orchestrator-form-react/src/components/OrchestratorFormWrapper.tsx


8. workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/ExecuteWorkflowPage.tsx ✨ Enhancement +9/-1

Integrate query param prepopulation into workflow execution page

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/ExecuteWorkflowPage.tsx


9. workspaces/orchestrator/plugins/orchestrator/package.json Dependencies +1/-0

Add json-schema-library dependency for schema resolution

workspaces/orchestrator/plugins/orchestrator/package.json


10. workspaces/orchestrator/.changeset/honor-schema-defaults.md 📝 Documentation +6/-0

Changeset for schema defaults feature

workspaces/orchestrator/.changeset/honor-schema-defaults.md


11. workspaces/orchestrator/.changeset/scope-async-validation-to-step.md 📝 Documentation +5/-0

Changeset for async validation scoping fix

workspaces/orchestrator/.changeset/scope-async-validation-to-step.md


12. workspaces/orchestrator/.changeset/tall-games-fail.md 📝 Documentation +5/-0

Changeset for query param prepopulation feature

workspaces/orchestrator/.changeset/tall-games-fail.md


13. workspaces/orchestrator/.changeset/unlucky-poems-drum.md 📝 Documentation +5/-0

Changeset for UI schema directive preservation fix

workspaces/orchestrator/.changeset/unlucky-poems-drum.md


14. workspaces/orchestrator/docs/user-interface.md 📝 Documentation +46/-0

Document Execute Workflow form prepopulation feature and usage

workspaces/orchestrator/docs/user-interface.md


Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge Bot commented Apr 1, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. allOf paths not recognized 🐞 Bug ≡ Correctness
Description
mergeQueryParamsIntoFormData can incorrectly ignore query params for schemas composed with allOf
because pathExistsInSchema only branches for oneOf/anyOf and otherwise requires a direct properties
object. This breaks prepopulation for workflows whose input schema uses top-level or nested allOf
composition.
Code

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[R55-86]

+/**
+ * Returns true if the path exists in the schema's properties (recursively).
+ * Handles $ref, oneOf, anyOf, allOf. Used to reject unknown query params.
+ */
+function pathExistsInSchema(
+  schema: JSONSchema7,
+  path: string,
+  root: JSONSchema7,
+): boolean {
+  if (!path) return true;
+  let s: JSONSchema7 | undefined = schema;
+  const parts = path.split('.');
+
+  for (let i = 0; i < parts.length; i++) {
+    const part = parts[i];
+    if (!s || typeof s === 'boolean') return false;
+    if (s.$ref) {
+      s = resolveRef(root, s.$ref);
+      i--;
+      continue;
+    }
+    if (s.oneOf || s.anyOf) {
+      const remaining = parts.slice(i).join('.');
+      return pathExistsInComposite(s, remaining, root);
+    }
+    const props = s.properties;
+    if (!props || typeof props !== 'object') return false;
+    if (!(part in props)) return false;
+    s = props[part] as JSONSchema7;
+  }
+  return true;
+}
Evidence
pathExistsInSchema claims it handles allOf but only delegates to pathExistsInComposite when
oneOf/anyOf is present; if a schema node is composed solely via allOf (common for schema reuse),
properties may be absent and the function returns false, rejecting otherwise valid paths. Although
pathExistsInComposite includes allOf branches, it is never reached for allOf-only nodes due to the
missing condition in pathExistsInSchema.

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[55-86]
workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[91-109]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`pathExistsInSchema` rejects valid query-param paths when the schema node uses `allOf` without also having `oneOf`/`anyOf`, because it only delegates composite traversal for `oneOf`/`anyOf` and otherwise requires `properties`.

### Issue Context
This causes query-param prepopulation to silently skip fields defined via schema composition (a common JSON Schema pattern).

### Fix Focus Areas
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[55-86]
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[91-109]

### Suggested fix
Update the composite-branch condition in `pathExistsInSchema` to include `allOf` as well (e.g., `if (s.oneOf || s.anyOf || s.allOf) ...`). Consider also adding a unit test covering a root schema with `allOf: [{ type:'object', properties:{ ... }}]` to prevent regression.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unsafe set path validation 🐞 Bug ⛨ Security
Description
mergeQueryParamsIntoFormData uses part in props to validate query param paths and then passes the
raw paramKey into lodash/set to build proposedData; in accepts prototype-chain keys like
__proto__, which can allow prototype-pollution-style paths to pass the guard and reach lodash/set.
This can cause unexpected behavior and potential security issues when processing untrusted URLs.
Code

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[R279-292]

+  for (const [paramKey, paramValue] of searchParams.entries()) {
+    if (RESERVED_QUERY_PARAMS.has(paramKey)) {
+      continue;
+    }
+    if (paramValue === undefined || paramValue === null) {
+      continue;
+    }
+
+    if (!pathExistsInSchema(schema, paramKey, schema)) continue;
+
+    // Build proposed data with raw value so getSchema can resolve oneOf/anyOf/if-then-else
+    const proposedData = cloneDeep(result) as JsonObject;
+    set(proposedData, paramKey, paramValue);
+
Evidence
The schema path guard uses the in operator, which checks inherited keys as well, and the code
calls lodash/set with the untrusted query param key before verifying the schema at that pointer is
resolvable. This combination makes it possible for prototype keys (e.g., __proto__) to bypass the
existence check and get written into the intermediate object.

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[80-83]
workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[279-299]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The query-param merge flow can write attacker-controlled paths into objects via `lodash/set`. The current guard uses `part in props`, which considers prototype-chain keys (e.g., `__proto__`), and `set(proposedData, paramKey, paramValue)` happens before schema resolution.

### Issue Context
Even if `getSchemaAtPath` later returns undefined and the param is skipped, the intermediate `set(proposedData, ...)` has already executed.

### Fix Focus Areas
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[59-86]
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[279-299]

### Suggested fix
1) Replace `if (!(part in props))` with an own-property check:
- `if (!Object.prototype.hasOwnProperty.call(props, part)) return false;`

2) Add explicit rejection of dangerous path segments before any `set()` call (defense-in-depth):
- Reject if any segment equals `__proto__`, `prototype`, or `constructor`.

3) Consider using a safe setter (or building `proposedData` without mutating prototypes) for the `proposedData` used in schema resolution.

Add a unit test that asserts params like `__proto__=x` and `constructor=y` are ignored and do not modify object prototypes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Const constraint not enforced 🐞 Bug ≡ Correctness
Description
Query param coercion allows arbitrary values for fields whose schema uses JSON Schema const
because isDefinedLeafSchema treats const as a settable leaf but the coercion logic never validates
the value against const. This can prefill invalid values and lead to unexpected validation
failures or incorrect schema-branch resolution.
Code

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[R125-219]

+function isDefinedLeafSchema(s: JSONSchema7 | undefined): boolean {
+  if (!s || typeof s === 'boolean') return false;
+  if (s.enum !== undefined || s.const !== undefined) return true;
+  const t = s.type;
+  if (Array.isArray(t)) return t.some(v => LEAF_TYPES.includes(v as any));
+  return t !== undefined && LEAF_TYPES.includes(t as any);
+}
+
+/**
+ * Gets the schema definition for a dot-notation path using json-schema-library.
+ * Resolves $ref, oneOf, anyOf, allOf, and if/then/else when data context is provided.
+ *
+ * @param schema - The root JSON Schema
+ * @param path - Dot-notation path (e.g. "mode.alphaValue")
+ * @param data - The data object at that path; required for oneOf/anyOf/if resolution
+ */
+function getSchemaAtPath(
+  schema: JSONSchema7,
+  path: string,
+  data: JsonObject,
+): JSONSchema7 | undefined {
+  if (!path) return undefined;
+
+  try {
+    const parsedSchema = new JsonSchema(schema);
+    const pointer = toJsonPointer(path);
+    const resolved = parsedSchema.getSchema({
+      pointer,
+      data,
+    });
+    if (!resolved || typeof resolved === 'boolean') return undefined;
+    const schemaObj = resolved as JSONSchema7;
+    const isLeaf = isDefinedLeafSchema(schemaObj);
+    return isLeaf ? schemaObj : undefined;
+  } catch {
+    return undefined;
+  }
+}
+
+/**
+ * Coerces a single string value for a scalar schema (used for array items).
+ */
+function coerceScalarValue(
+  strParam: string,
+  itemSchema: JSONSchema7 | undefined,
+): JsonValue | undefined {
+  if (!itemSchema) return strParam;
+
+  const enumValues = itemSchema.enum as
+    | (string | number | boolean)[]
+    | undefined;
+  const hasEnum =
+    enumValues && Array.isArray(enumValues) && enumValues.length > 0;
+
+  if (hasEnum) {
+    if (enumValues!.includes(strParam)) return strParam;
+    for (const enumVal of enumValues!) {
+      if (typeof enumVal === 'boolean') {
+        const lower = strParam.toLowerCase();
+        if (
+          (lower === 'true' && enumVal === true) ||
+          (lower === 'false' && enumVal === false)
+        ) {
+          return enumVal;
+        }
+      } else if (typeof enumVal === 'number') {
+        const parsed = Number(strParam);
+        if (!Number.isNaN(parsed) && parsed === enumVal) return parsed;
+      } else if (typeof enumVal === 'string') {
+        if (enumVal.toLowerCase() === strParam.toLowerCase()) return enumVal;
+      }
+    }
+    return undefined;
+  }
+
+  if (itemSchema.type === 'boolean') {
+    const lower = strParam.toLowerCase();
+    if (lower === 'true') return true;
+    if (lower === 'false') return false;
+    return undefined;
+  }
+  if (itemSchema.type === 'integer') {
+    const parsed = Number(strParam);
+    if (!Number.isNaN(parsed) && Number.isInteger(parsed)) return parsed;
+    return undefined;
+  }
+  if (itemSchema.type === 'number') {
+    const parsed = Number(strParam);
+    if (!Number.isNaN(parsed)) return parsed;
+    return undefined;
+  }
+
+  // string or unspecified type
+  return strParam;
+}
Evidence
The code explicitly treats const as a supported leaf constraint, but coerceScalarValue only
enforces enum and basic types and otherwise returns the raw string; therefore const-constrained
fields are not validated and any value will be merged.

workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[125-131]
workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[167-219]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Fields with JSON Schema `const` constraints are treated as eligible for prepopulation, but their query-param values are not checked against the `const` value.

### Issue Context
`isDefinedLeafSchema` returns true when `s.const` is present, but coercion currently only implements `enum` and type-based parsing.

### Fix Focus Areas
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[125-131]
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[167-219]

### Suggested fix
In `coerceScalarValue`, add a `const` handling block before `enum`:
- If `itemSchema.const` is defined, attempt to coerce `strParam` to the const’s type (string/number/boolean) and return it only when it equals `itemSchema.const`; otherwise return `undefined`.
Add a unit test covering a `const` field (and optionally a `const` discriminator inside `oneOf`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 1, 2026

Copy link
Copy Markdown
Member

@karthikjeeyar karthikjeeyar left a comment

Choose a reason for hiding this comment

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

/approve
/lgtm

Comment on lines +55 to +86
/**
* Returns true if the path exists in the schema's properties (recursively).
* Handles $ref, oneOf, anyOf, allOf. Used to reject unknown query params.
*/
function pathExistsInSchema(
schema: JSONSchema7,
path: string,
root: JSONSchema7,
): boolean {
if (!path) return true;
let s: JSONSchema7 | undefined = schema;
const parts = path.split('.');

for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (!s || typeof s === 'boolean') return false;
if (s.$ref) {
s = resolveRef(root, s.$ref);
i--;
continue;
}
if (s.oneOf || s.anyOf) {
const remaining = parts.slice(i).join('.');
return pathExistsInComposite(s, remaining, root);
}
const props = s.properties;
if (!props || typeof props !== 'object') return false;
if (!(part in props)) return false;
s = props[part] as JSONSchema7;
}
return true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Allof paths not recognized 🐞 Bug ≡ Correctness

mergeQueryParamsIntoFormData can incorrectly ignore query params for schemas composed with allOf
because pathExistsInSchema only branches for oneOf/anyOf and otherwise requires a direct properties
object. This breaks prepopulation for workflows whose input schema uses top-level or nested allOf
composition.
Agent Prompt
### Issue description
`pathExistsInSchema` rejects valid query-param paths when the schema node uses `allOf` without also having `oneOf`/`anyOf`, because it only delegates composite traversal for `oneOf`/`anyOf` and otherwise requires `properties`.

### Issue Context
This causes query-param prepopulation to silently skip fields defined via schema composition (a common JSON Schema pattern).

### Fix Focus Areas
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[55-86]
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[91-109]

### Suggested fix
Update the composite-branch condition in `pathExistsInSchema` to include `allOf` as well (e.g., `if (s.oneOf || s.anyOf || s.allOf) ...`). Consider also adding a unit test covering a root schema with `allOf: [{ type:'object', properties:{ ... }}]` to prevent regression.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +279 to +292
for (const [paramKey, paramValue] of searchParams.entries()) {
if (RESERVED_QUERY_PARAMS.has(paramKey)) {
continue;
}
if (paramValue === undefined || paramValue === null) {
continue;
}

if (!pathExistsInSchema(schema, paramKey, schema)) continue;

// Build proposed data with raw value so getSchema can resolve oneOf/anyOf/if-then-else
const proposedData = cloneDeep(result) as JsonObject;
set(proposedData, paramKey, paramValue);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Unsafe set path validation 🐞 Bug ⛨ Security

mergeQueryParamsIntoFormData uses part in props to validate query param paths and then passes the
raw paramKey into lodash/set to build proposedData; in accepts prototype-chain keys like
__proto__, which can allow prototype-pollution-style paths to pass the guard and reach lodash/set.
This can cause unexpected behavior and potential security issues when processing untrusted URLs.
Agent Prompt
### Issue description
The query-param merge flow can write attacker-controlled paths into objects via `lodash/set`. The current guard uses `part in props`, which considers prototype-chain keys (e.g., `__proto__`), and `set(proposedData, paramKey, paramValue)` happens before schema resolution.

### Issue Context
Even if `getSchemaAtPath` later returns undefined and the param is skipped, the intermediate `set(proposedData, ...)` has already executed.

### Fix Focus Areas
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[59-86]
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/queryParamsToFormData.ts[279-299]

### Suggested fix
1) Replace `if (!(part in props))` with an own-property check:
- `if (!Object.prototype.hasOwnProperty.call(props, part)) return false;`

2) Add explicit rejection of dangerous path segments before any `set()` call (defense-in-depth):
- Reject if any segment equals `__proto__`, `prototype`, or `constructor`.

3) Consider using a safe setter (or building `proposedData` without mutating prototypes) for the `proposedData` used in schema resolution.

Add a unit test that asserts params like `__proto__=x` and `constructor=y` are ignored and do not modify object prototypes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@karthikjeeyar karthikjeeyar merged commit c3fc338 into workspace/orchestrator Apr 1, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants